home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Hardware / cnetdevice / src / cnetdevice.asm < prev    next >
Encoding:
Assembly Source File  |  2002-10-27  |  139.1 KB  |  5,384 lines

  1. ;---------------------------------------------------------------------------
  2. ;                  PCMCIA ethernet card driver for A600/A1200
  3. ;---------------------------------------------------------------------------
  4. ;
  5. ; HISTORY:
  6. ;
  7. ; 10-4-97  v0.1 - Created by Bruce Abbott (bhabbott@inhb.co.nz)
  8. ;                      *** First Aminet Release ***
  9. ;
  10. ; 29-4-97  v0.2 - Implemented CMD_ONLINE/OFFLINE/FLUSH (for Miami).
  11. ;
  12. ;               - Enabled interrupts during RemoteWrite (no more serial
  13. ;                 port overruns!).
  14. ;
  15. ; 6-5-97   v0.3 - Added a flag so that we won't try to ReleaseCard()
  16. ;                 unless there was a successful OwnCard()!
  17. ;
  18. ; 17-5-97  v0.4 - CMD_CONFIGINTERFACE now overrides the default hardware
  19. ;                 address (for Miami).
  20. ;
  21. ;               - Device now goes offline if the PCMCIA card is removed.
  22. ;
  23. ;               - CMD_ONEVENT implemented.
  24. ;
  25. ;               - Loosened hardware address verification to accept the
  26. ;                 Accton EN2216.
  27. ;
  28. ;               - Unrolled loops to improve data transfer speed. Now
  29. ;                 about 20% faster on an unexpanded A600.
  30. ;
  31. ;               - Hack to fix problem with missed interrupts. Now we
  32. ;                 clear the Gayle interrupt bits instead of letting
  33. ;                 card.resource do it for us.
  34. ;
  35. ;                        *** Second Aminet Release ***
  36. ;
  37. ; 29-7-97  v0.5 - Accepts 802.3 packets (untested).
  38. ;
  39. ;               - Sets BROADCAST bit in io_flags when appropriate.
  40. ;
  41. ;               - Now examines PCMCIA attribute memory to determine
  42. ;                 value to write into Card Configuration Register.
  43. ;
  44. ;               - If attribute memory not found, tries to open the file
  45. ;                 "s:cnetdev.config" to get Card Configuration Register
  46. ;                 offset, Configuration ID, and ROM Station Address.
  47. ;
  48. ;                        *** Third Aminet Release ***
  49. ;
  50. ;22-12-97 v0.6 - I/O addressing now supports 64KByte range (was 1KB).
  51. ;
  52. ;              - Tighter data transfer loops, slightly faster on '030.
  53. ;
  54. ;              - Accepts all Card Configuration Register address sizes.
  55. ;
  56. ;              - Removed cnet.config stuff (replaced with hardware mod).
  57. ;
  58. ;              - Now cards are hot-swappable.
  59. ;
  60. ;              - Un-supported commands now return S2ERR_NOT_SUPPORTED.
  61. ;
  62. ;                        *** 4th Aminet Release ***
  63. ;
  64. ;21-4-98 v0.7  - fixed harmless bug in init_nic - remote DMA timeout test
  65. ;                could not fail!
  66. ;
  67. ;              - Now remembers copytobuf/copyfrombuf tags for each opener.
  68. ;                Allows simultaneous use of eg. AmiTCP and Envoy.
  69. ;
  70. ;              - OnEvent types ONLINE and OFFLINE now return immediately
  71. ;                if the device is already in the wanted state.
  72. ;
  73. ;                        *** 5th Aminet Release ***
  74. ;
  75. ;17-12-98 v0.8 - fixed bug in OnEvent: was using wrong register to test
  76. ;                ONLINE flag.
  77. ;
  78. ; 1-6-99 v0.9  - Added support for multicasting, statistics, orphan packets,
  79. ;                exclusive and promiscuous modes.
  80. ;
  81. ;                        *** 6th Aminet Release ***
  82. ;
  83. ; 5-7-99 v1.0  - Fixed bug in readpacket: MCAST flag was also set when packet
  84. ;                was BCAST.
  85. ;
  86. ;                        *** 7th Aminet Release ***
  87. ;
  88. ; 7-7-99 v1.1  - Fixed bug: delmulticast always failed due to bad testing
  89. ;                for multicast address match.
  90. ;
  91. ;              - Fixed bug: readpacket was getting incorrect src and dst
  92. ;                addresses (A4 was pointing to prhdr instead of etherhdr).
  93. ;
  94. ;              - Included put_multi in init_nic (need to reload multicast
  95. ;                bits if card is removed and re-inserted)
  96. ;
  97. ;              - Added 4 to rx ios2_datalength in raw mode. Shapeshifter
  98. ;                seems to need this (why?)
  99. ;
  100. ;                        *** 8th Aminet release ***
  101. ;
  102. ;7-5-00 v1.2b1 - Since there has been almost ten months without an update,
  103. ;                I, Harry Sintonen <sintonen@iki.fi>, decided to have a go.
  104. ;
  105. ;              - Reformatted this source code: Now registers are always in
  106. ;                lowercase, for better readability.
  107. ;
  108. ;              - Added MN_LENGTH check for OpenDevice() (S2R3 and NSD require
  109. ;                this).
  110. ;
  111. ;              - Fixed a bug: If TAG_IGNORE, TAG_MORE or TAG_SKIP were used
  112. ;                in the IOSana2Req's taglist Open_Unit got really confused,
  113. ;                throwing enforcer hits, and in a worst case, crashing the
  114. ;                machine. Now uses utility.library GetTagData().
  115. ;
  116. ;              - Optimized dbf loops to subq + branch for better 020+
  117. ;                performance. Made several other miscallenous optimizations
  118. ;                thruout the code.
  119. ;
  120. ;              - More bugs fixed: DoEvent examined dd_eventlist before
  121. ;                Disable(). devcmd_addmulticast and devcmd_delmulticast
  122. ;                didn't lock the list, devcmd_delmulticast called Enable()
  123. ;                without Disable() when no multicast was found. Protected
  124. ;                dd_multicasts list with semaphore. dd_bufmanlist was
  125. ;                accessed without list arbitration, added Disable()/Enable()
  126. ;                pair when needed.
  127. ;
  128. ;              - Added support for S2_PacketFilter tag. Speedup: replaced
  129. ;                several list related calls with macros.
  130. ;
  131. ;              - Rewrote CMD_READ handling: Added proper Multiple Protocol
  132. ;                Stack Support, it was really broken before. Basically this
  133. ;                means that each opener gets all the packets necessary. If a
  134. ;                packet comes in that fills a request for more than one
  135. ;                opener of the device, *all* of them will get a copy of the
  136. ;                packet. Of course each caller can ask RAW or non-RAW version
  137. ;                of the packet. cnet.device fully comply to S2R2 now!
  138. ;
  139. ;              - Since complies to S2R2, added NewStyleDevice (NSD) support.
  140. ;                Also added S2R3 S2_DMACopyFromBuff32 tag support, however
  141. ;                this feature is currently disabled. ***
  142. ;                S2_DMACopyToBuff32 would only pay off if: 1) there is only
  143. ;                one caller for this packet, and 2) there is no packet filter
  144. ;                for this caller.
  145. ;
  146. ;              - More speedups: Replaced exec Disable() and Enable() calls
  147. ;                with macros. Yet more list related calls replaced with
  148. ;                macros.
  149. ;
  150. ;              - Yet more bugs fixed: CMD_FLUSH didn't abort S2_READORPHANs.
  151. ;                CMD_OFFLINE didn't abort pending CMD_READs, S2_READORPHANs
  152. ;                and CMD_WRITEs. CMD_READ and S2_READORPHAN didn't check for
  153. ;                card being online. S2_ONEVENT didn't check if it knows the
  154. ;                event condition(s) specified, instead requests for unknown
  155. ;                event(s) would never have got returned. Also S2_ONEVENT
  156. ;                returned the ioreq even if it was queued. S2_CONFIGINTERFACE
  157. ;                worked more than once, it *must* only work once.
  158. ;                OpenDevice() incorrectly required S2_CopyFromBuff and
  159. ;                S2_CopyToBuff tags to be present.
  160. ;
  161. ;              - Yet more speedups: DoEvent uses global cached device
  162. ;                pointer.
  163. ;
  164. ;              - init_card and init_nic fire S2EVENT_ERROR|S2EVENT_HARDWARE
  165. ;                event if something goes wrong. Trying to send too big of a
  166. ;                packet trigger S2EVENT_TX. If packet gets dropped during
  167. ;                receive S2EVENT_ERROR|S2EVENT_RX event is triggered. If
  168. ;                copyfrombuf while transmitting fails S2EVENT_TX|S2EVENT_BUFF
  169. ;                event is triggered, and similarily if copytobuf while
  170. ;                receiving fails S2EVENT_RX|S2EVENT_BUFF event is triggered.
  171. ;
  172. ;              - Extensively debugged for 18+6 hours to make 1st early beta
  173. ;                possible...
  174. ;
  175. ;              - Currently at least following should work: CMD_READ,
  176. ;                CMD_WRITE, CMD_FLUSH, S2_DEVICEQUERY, S2_GETSTATIONADDRESS,
  177. ;                S2_CONFIGINTERFACE, S2_ADDMULTICASTADDRESS,
  178. ;                S2_DELMULTICASTADDRESS, S2_MULTICAST, S2_BROADCAST,
  179. ;                S2_TRACKTYPE, S2_UNTRACKTYPE, S2_GETTYPESTATS,
  180. ;                S2_GETSPECIALSTATS, S2_GETGLOBALSTATS, S2_ONEVENT,
  181. ;                S2_READORPHAN, S2_ONLINE, S2_OFFLINE and NSCMD_DEVICEQUERY.
  182. ;
  183. ;              - Tested with sanamon, sanautil, miamidx and genesis.
  184. ;
  185. ;                        *** internal 1.2beta1 release ***
  186. ;
  187. ;9-5-00 v1.2b2 - initRoutine trashed a6 by leaving execbase in it, but since
  188. ;                it *is* execbase originally it was harmless. Silly. :)
  189. ;
  190. ;              - Misc minor changes here and there.
  191. ;
  192. ;              - Added device expunge. esp. cool for debugging, no more those
  193. ;                damn annoying reboots. Also someone might want to quit
  194. ;                protocol stack, avail flush, and use some other card without
  195. ;                the need to reboot. Now DDF_CONFIGURED is reset only on
  196. ;                device flush, this means that pulling the card out doesn't
  197. ;                cut the connection anymore, and you can continue by plugging
  198. ;                the card back in. v1.2b1 didn't allow this hot swapping
  199. ;                trick, but v1.1 did.
  200. ;
  201. ;              - Bugfixes: initRoutine crashed if utility.library v36 failed
  202. ;                to open. Partially successful OpenDevice ate some resources,
  203. ;                now it should be able to back out in all cases. S2_OFFLINE
  204. ;                should, I quote: "Aborts all pending reads and writes with
  205. ;                ios2_Error set to S2ERR_OUTOFSERVICE.". However this makes
  206. ;                MiamiDx die a horrible death. Took me 10 hours to find why.
  207. ;                Damn it! Disabled IO aborting and now it works. D'oh!
  208. ;
  209. ;              - Speedup: Implemented turbo RemoteRead & RemoteWrite loops,
  210. ;                they use longword access to 16bit register. Don't worry,
  211. ;                this works, but honestly I have no clue why. Enabled DMA for
  212. ;                both regular and raw CMD_WRITEs. At least MiamiDx support
  213. ;                S2_DMACopyFromBuff32. Moving 30mb mpg between my amiga and
  214. ;                laptop result about 450kb/s upload and 500kb/s download
  215. ;                speed. v1.1 and the same environment gave about 420kb/s
  216. ;                upload and 450kb/s download speed.
  217. ;                (ftp client AmFTP 1.92, ftpd Version 6.2/OpenBSD/Linux-0.10)
  218. ;
  219. ;              - Made Makefile generate 68000 version of the device. No real
  220. ;                differences yet tho. this version is untested!
  221. ;
  222. ;                        *** internal 1.2beta2 release ***
  223. ;
  224. ;16-5-00 v1.2b3  Got a report that v1.2b2 is actually slower than v1.2b1.
  225. ;                Well I wrote a simple AmigaE program that I can use to
  226. ;                benchmark cnet.device CMD_WRITE. Turned out that turboio
  227. ;                transfer ~679kb/s and non-turboio 697kb/s without DMA
  228. ;                transfer, in DMA mode the same figures are 694kb/s vs. 713
  229. ;                kb/s. Oh dear, this is it, I disabled turboio. :) Thanks go
  230. ;                to Tundrah for the tip. BTW: it seems we're finally getting
  231. ;                there, he get ~770kb/s real life transfer speed using FTP
  232. ;                (Apollo ethernet, 060 @ 66). Not bad. Btw benchmarking
  233. ;                CMD_READ is a bit problematic for me as I don't have really
  234. ;                state of the art machine on the other end and it can't feed
  235. ;                the card at the full speed. However Tundrah also told me
  236. ;                that for some reason MiamiDx is slow compared to Genesis. I
  237. ;                did some tests with both MiamiDx and Genesis, used ftp
  238. ;                client AmFTP 1.92 and ftpd Version 6.2/OpenBSD/Linux-0.10.
  239. ;                Download speed with Genesis was 720kb/s and with MiamiDx 530
  240. ;                kb/s. Genesis is %33 faster. For fucks sake wtf Miami is
  241. ;                doing? busyloops or what? :) This probably means that
  242. ;                someone should make a MNI driver. Any volunteers?
  243. ;
  244. ;              - Forget that mumbo jumbo about MMU speedup hack that was
  245. ;                mentioned in v1.2b2. 1) no real speedup due the way I/O
  246. ;                is accessed. 2) many amiga 060 turbo cards don't have
  247. ;                special hardware to handle writebuffer burst write ->
  248. ;                undefined behavior. (Thanks to Ralph Schmidt for helping me
  249. ;                understand this)
  250. ;
  251. ;              - Bugfix: AbortIO failed to abort S2_MULTICAST or S2_BROADCAST
  252. ;                requests.
  253. ;                
  254. ;                        *** internal 1.2beta3 release ***
  255. ;
  256. ;19-5-00 v1.2b4  Misc little changes here and there, nothing major.
  257. ;
  258. ;              - Speedup: inlined optimized version of RemoteRead for reading
  259. ;                prhdr and etherheader. Joined rx_header and rxbuffer. As a
  260. ;                result code simplified and sped up. For me the speedup is
  261. ;                +2kb/s. Inlined couple of other subroutines that are called
  262. ;                only once.
  263. ;
  264. ;              - Speedup: Got a report from darza saying that turboio indeed
  265. ;                is faster with `cnet' card. He got 720kb/s with v1.1,
  266. ;                v1.2beta1 and v1.2beta3, but 750kb/s with v1.2beta2. Eek! :)
  267. ;                Tweaked makefile to compile separate turboio version. It is
  268. ;                up to user to find out which one is faster. Currently non-
  269. ;                turboio ftp download peaked 754kb/s. Turboio version peaked
  270. ;                771kb/s. Could be that turboio is faster on 060 @ 50 systems
  271. ;                and non-turboio on overclocked 060 systems. Why? Maybe some
  272. ;                I/O timing issues... No idea really, just guessing. Need to
  273. ;                ask Tundrah to do more benchmarking. :)
  274. ;
  275. ;              - Improvements: added support for S2_ADDMULTICASTADDRESSES and
  276. ;                S2_DELMULTICASTADDRESSES (Multicast address range extensions
  277. ;                to SANA-II Rev 3). Implemented S2_ADDMULTICASTADDRESS and
  278. ;                S2_DELMULTICASTADDRESS using range of addr -> addr. Added
  279. ;                CPU type to version string. Added 68020 CPU check to 68020+
  280. ;                version. Device IDString no longer has '$VER: ' included.
  281. ;                Now uses CARDF_POSTSTATUS instead of a hack if card.resource
  282. ;                V39+ is available (note that KS 3.0 has *V37* card.resource,
  283. ;                and KS 3.1 has V40). Added workaround for Genesis bug, it
  284. ;                calls S2_ONLINE before S2_CONFIGINTERFACE.
  285. ;
  286. ;                        *** internal 1.2beta4 release ***
  287. ;
  288. ;25-5-00 v1.2  - Made compile with standard os-includes.
  289. ;
  290. ;                        *** 9th Aminet release ***
  291. ;
  292. ;19-8-00 v1.3b1  Disabled some unused code. Size optimized some non-time
  293. ;                critical code.
  294. ;
  295. ;              - Speedup: Implemented one obvious 020 optimization. Thanks to
  296. ;                Ilkka Lehtoranta for pointing it out.
  297. ;
  298. ;              - Improvement: Now uses memory pool for all memory allocations
  299. ;                to prevent memory fragmentation. Also a bit faster than
  300. ;                using exec AllocMem/FreeMem since uses semaphore for access
  301. ;                arbitration (exec memroutines use Forbid/Permit).
  302. ;
  303. ;                        *** internal 1.3beta1 release ***
  304. ;
  305. ; 1-9-00 v1.3  - Aminet release recompile.
  306. ;
  307. ;                        *** 10th Aminet release ***
  308. ;
  309. ; 7-9-00 v1.4  - Fixed serious memory trashing bug from OpenDevice: two long-
  310. ;                words pointed by a2 register were trashed! The actual bug
  311. ;                was in get_time that is called by init_nic that is called by
  312. ;                Open_Device. This bug was introduced in v1.2b2. Special
  313. ;                thanks and hellos go to Ralph Schmidt for hunting down this
  314. ;                bug (he had to do lots and lots of extra work just to locate
  315. ;                it), and please, don't kill me :-) This bug was very nasty
  316. ;                and totally, utterly my fault. But hey, shit happens.
  317. ;
  318. ;                        *** 11th Aminet release ***
  319. ;
  320. ;2-11-00 v1.5  - Now assumes network card if CISTPL_FUNC_ID tuple isn't found.
  321. ;                Makes the device work with some cards that failed before.
  322. ;                (Colin Willans, Neil Cafferkey)
  323. ;
  324. ;              - Fixed a bug from pre-V39 FreePooled() -routine. I thought I
  325. ;                had already fixed it, but no. ouch.
  326. ;
  327. ;                        *** 12th Aminet release ***
  328. ;
  329. ; 4-1-01 v1.6  - Bugfix: S2_GETSTATIONADDRESS returned current interface
  330. ;                address in both ios2_SrcAddr and ios2_DstAddr. Now
  331. ;                ios2_DstAddr return the factory default station address as
  332. ;                supposed to.
  333. ;
  334. ;              - Bugfix: S2_TRACKTYPE and S2_UNTRACKTYPE called alloc & free
  335. ;                within Disable(). Caused terrible lockup if semaphore wasn't
  336. ;                free or owned by the caller. Fixed.
  337. ;
  338. ;              - Bugfix: S2_ONLINE trashed one byte of memory if device
  339. ;                wasn't configured. Grrrh, I hate assembler. Fixed.
  340. ;
  341. ;              - Bugfix: In some special conditions OwnCard() could have got
  342. ;                called more than once. Oops. Fixed.
  343. ;
  344. ;              - Source cleanup: Removed redundant 'moveq #0,d0' from soft
  345. ;                interrupts, localized/moved to device base some global
  346. ;                variables. Removed get_time completely, added proper
  347. ;                timer.device open and cleanup. Moved OpenResource to device
  348. ;                initroutine. Disabled some unused code. Removed some unused
  349. ;                device flags.
  350. ;
  351. ;              - Added EasyRequest for some of the initialization errors.
  352. ;                Should help users to identify hardware problems.
  353. ;
  354. ;              - Added DMA timeout test for reads, might fix some cards that
  355. ;                failed before (timing problems).
  356. ;
  357. ;              - Improvement: Now set iorequest error code properly on write
  358. ;                error.
  359. ;
  360. ;                        *** 13th & 14th Aminet release ***
  361. ;
  362. ;11-7-01 v1.7  - Bugfix: Recovering from receiver ring buffer overflow caused
  363. ;                NIC to stop accepting multicast packets (broadcast packets were
  364. ;                still accepted though). Also possible promiscous mode was turned
  365. ;                off. Now always reset the receive mode to current one. Also
  366. ;                disabled unused dd_overflows counter.
  367. ;
  368. ;              - Bugfix: Promiscous mode didn't accept all multicast addresses.
  369. ;                Fixed to do so.
  370. ;
  371. ;                        *** 15th Aminet release ***
  372. ;
  373. ;27-10-02 v1.8 - Bugfix: deviceinit leaked memory if it failed.
  374. ;
  375. ;                        *** 16th Aminet release ***
  376. ;
  377.  
  378.  
  379. ; todo: Incorporate automatic CardReset if CISTPL_CONF_MAP tuple (or other tuples) is
  380. ;       not found, or if card reset fails.
  381. ;       move.b #$ff,$00da9000
  382. ;       ; delay
  383. ;       move.b #$00,$00da9000
  384. ;
  385. ;       Add double buffering to write (TBUF1)
  386. ;       Do some more 020+ optimizations (the ones that really pay off!)
  387. ;       CopyTo/CopyFrom 16/32 support? (ADCD_2.1:DevInfo/Networking/SANA2Revision3)
  388. ;       Add support for more cards? (not in this device in this life, unless easily implemented)
  389. ;
  390.  
  391.  
  392. ; configured from makefile
  393. ;debug = 1
  394. ;verbose=1
  395. ;turboio = 1
  396.  
  397. ; misc flags
  398. ;realdisable=1    ; use exec functions or macros ?
  399. ;softintdisable=1 ; disable just softint or all ints ? (doesn't work!)
  400. ;nosendthrottle=1 ; avoid unnecessary interrupts on CMD_WRITE
  401. pedanticread=1   ; do DMA timeout for read, seem to be unnececcary
  402. nocmdsave=1      ; don't save command (in fact page select, always page 0 if not disabled)
  403.  
  404. ; debug output related flags
  405. ;errordebonly=1   ; supress normal operation debug, only show abnormal stuff
  406.  
  407. ; DMA write wait timeout
  408. DMATIMEOUT = 30000
  409.  
  410. DEF_TCR = $00
  411. ;;DEF_TCR  = DSTC_OFST
  412.  
  413.  
  414.  include exec/types.i
  415.  include exec/nodes.i
  416.  include exec/lists.i
  417.  include exec/libraries.i
  418.  include exec/errors.i
  419.  include exec/initializers.i
  420.  include exec/resident.i
  421.  include exec/memory.i
  422.  include exec/interrupts.i
  423.  include exec/semaphores.i
  424.  include exec/ports.i
  425.  include exec/io.i
  426.  include exec/devices.i
  427.  include devices/timer.i
  428.  IFND realdisable
  429.  include exec/ables.i
  430.  ENDC
  431.  
  432.  include funcdef.i
  433.  include exec/exec_lib.i
  434.  
  435.  IFND _LVOGetSysTime
  436. _LVOGetSysTime = -66          ; timer lib function
  437.  ENDC
  438.  IFND _LVOGetTagData
  439. _LVOGetTagData = -36          ; utility lib function
  440.  ENDC
  441.  
  442.  IFND _LVOEasyRequestArgs
  443. _LVOEasyRequestArgs = -588    ; intuition.library
  444.  ENDC
  445.  
  446.  include pcmcia.i     ; card.resource etc.
  447.  include sanaii.i     ; the essential network stuff
  448.  include cnet.i       ; hardware specific stuff
  449.  
  450.  
  451. VERSION  = 1
  452. REVISION = 7
  453.  
  454. VERSTR macro
  455.  dc.b   "1.8 (27.10.2002)"
  456.  endm
  457.  
  458.  
  459. ; 1uS delay before nic register access
  460. ; May not be required with slower CPUs.
  461.  
  462. delay MACRO
  463. ; tst.b   $bfe001             ; at least 1uS, even on fast machines
  464.  ENDM
  465.  
  466.  
  467. MYDISABLE MACRO
  468.  IFD     realdisable
  469.  jsr     _LVODisable(a6)
  470.  ELSE
  471.  MOVE.W  #$4000,$DFF09A
  472.  ADDQ.B  #1,IDNestCnt(a6)
  473.  ENDC
  474.  ENDM
  475.  
  476. MYENABLE MACRO
  477.  IFD     realdisable
  478.  jsr     _LVOEnable(a6)
  479.  ELSE
  480.  SUBQ.B  #1,IDNestCnt(a6)
  481.  BGE.S   .MYENABLE\@
  482.  MOVE.W  #$C000,$DFF09A
  483. .MYENABLE\@:
  484.  ENDC
  485.  ENDM
  486.  
  487. SOFTDISABLE MACRO
  488.  IFD     softintdisable
  489.  ; Forbid task switching
  490.  addq.b  #1,TDNestCnt(a6)
  491.  ; Disable software interrupt
  492.  move.w  #$0004,$DFF09A
  493.  ELSE
  494.  MYDISABLE
  495.  ENDC
  496.  ENDM
  497.  
  498. SOFTENABLE MACRO
  499.  IFD     softintdisable
  500.  ; Enable software interrupt
  501.  move.w  #$8004,$DFF09A
  502.  ; Permit task switching
  503.  jsr     _LVOPermit(a6)
  504.  ELSE
  505.  MYENABLE
  506.  ENDC
  507.  ENDM
  508.  
  509. MYREMHEAD MACRO
  510.  MOVE.L  (A0),A1
  511.  MOVE.L  (A1),D0
  512.  BEQ.S   .MYREMHEAD\@
  513.  MOVE.L  D0,(A0)
  514.  EXG.L   D0,A1
  515.  MOVE.L  A0,LN_PRED(A1)
  516. .MYREMHEAD\@
  517.  ENDM
  518.  
  519. ;===========================================================================
  520.  
  521.  
  522.     section 0,CODE
  523.  
  524.  
  525. ;-----------------------------------------------------------------------
  526. ; The first executable location.  This should return an error
  527. ; in case someone tried to run you as a program (instead of
  528. ; loading you as a device).
  529.  
  530. start_exe:
  531.  moveq   #-1,d0   ; it's a device, not an application!
  532.  rts
  533.  
  534.  
  535. ;-----------------------------------------------------------------------
  536. ; A romtag structure.  After your driver is brought in from disk, the
  537. ; disk image will be scanned for this structure to discover magic constants
  538. ; about you (such as where to start running you from...).
  539. ;-----------------------------------------------------------------------
  540.  
  541. romtag:
  542.  dc.w    RTC_MATCHWORD   ; RT_MATCHWORD
  543.  dc.l    romtag          ; RT_MATCHTAG
  544.  dc.l    Endcode         ; RT_ENDSKIP
  545.  dc.b    RTF_AUTOINIT    ; RT_FLAGS
  546.  dc.b    VERSION         ; RT_VERSION
  547.  dc.b    NT_DEVICE       ; RT_TYPE
  548.  dc.b    0               ; RT_PRI
  549.  dc.l    DeviceName      ; RT_NAME
  550.  dc.l    IDString        ; RT_IDSTRING
  551.  dc.l    Init            ; RT_INIT
  552.  
  553. Init:
  554.  dc.l    dd_extsize      ; data space size
  555.  dc.l    funcTable       ; pointer to function initializers
  556.  dc.l    dataTable       ; pointer to data initializers
  557.  dc.l    initRoutine     ; routine to run at startup
  558.  
  559. funcTable:
  560.  dc.w  -1
  561.  dc.w  Open_Device-funcTable
  562.  dc.w  Close_Device-funcTable
  563.  dc.w  Expunge_Device-funcTable
  564.  dc.w  _Null-funcTable
  565.  dc.w  _DevBeginIO-funcTable
  566.  dc.w  _DevAbortIO-funcTable
  567.  dc.w  -1
  568.  
  569. dataTable:
  570.  INITBYTE LN_TYPE,NT_DEVICE
  571.  INITLONG LN_NAME,DeviceName
  572.  INITBYTE LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  573.  INITWORD LIB_VERSION,VERSION
  574.  INITWORD LIB_REVISION,REVISION
  575.  INITLONG LIB_IDSTRING,idString
  576.  dc.w   0
  577.  
  578.  
  579.  include debugs.i
  580.  
  581.  
  582.  
  583. ;=======================================================
  584. ;                      initRoutine
  585. ;=======================================================
  586. ;
  587. ; This routine gets called after the device has been allocated.
  588. ; The device pointer is in d0.  The AmigaDOS segment list is in a0.
  589. ; If it returns the device pointer, then the device will be linked
  590. ; into the device list. If it returns NULL, then the device will
  591. ; be unloaded. This call is single-threaded.
  592. ;
  593. ; input:   a0 = seglist
  594. ;          d0 = device
  595. ;          a6 = execbase
  596. ;
  597. initRoutine:
  598.  movem.l d1-d7/a0-a5,-(sp)
  599.  move.l  d0,a5
  600.  move.l  a0,a4
  601.  
  602.  ifge    __CPU-68020
  603.  btst    #AFB_68020,AttnFlags+1(a6)
  604.  beq     .no020
  605.  endc
  606.  
  607.  lea     cardname(pc),a1
  608.  jsr     _LVOOpenResource(a6) ; open credit card resource
  609.  move.l  d0,dd_cardres(a5)
  610.  beq     .no_cardres
  611.  
  612.  lea     utilityName(pc),a1
  613.  moveq   #36,d0
  614.  jsr     _LVOOpenLibrary(a6)
  615.  move.l  d0,dd_utilitybase(a5) ; store utilitybase
  616.  beq    .no_utility         ; oops failed, return failure
  617.  
  618.  lea     timerdevname(pc),a0 ; open timer.device
  619.  lea     dd_timereq(a5),a1
  620.  moveq   #UNIT_VBLANK,d0
  621.  move.b  #NT_REPLYMSG,ln_type(a1)
  622.  moveq   #0,d1
  623.  move.w  #iotv_size,mn_length(a1)
  624.  jsr     _LVOOpenDevice(a6)
  625.  tst.b   d0
  626.  bne     .no_timerdev
  627.  
  628.  move.l  #MEMF_PUBLIC|MEMF_CLEAR,d0 ; memFlags
  629.  move.l  #2048,d1            ; puddleSize
  630.  move.l  d1,d2               ; threshSize
  631.  bsr     createpool
  632.  move.l  d0,poolptr          ; store poolheader ptr
  633.  beq     .nopool             ; oh crap, failed to create!
  634.  
  635.  lea     poolsema(pc),a0     ; init mempool-semaphore
  636.  jsr     _LVOInitSemaphore(a6)
  637.  
  638.  
  639. ; init device data structures
  640.  
  641.  lea     dd_orphanlist(a5),a0          ; New MinList for orphan queue
  642.  bsr     _newlist
  643.  lea     dd_writelist(a5),a0           ; New MinList for write queue
  644.  bsr     _newlist
  645.  lea     dd_eventlist(a5),a0           ; New MinList for event queue
  646.  bsr     _newlist
  647.  lea     dd_bufmanlist(a5),a0          ; New MinList for bufman vectors
  648.  bsr     _newlist
  649.  lea     dd_tracklist(a5),a0           ; New MinList for tracking
  650.  bsr     _newlist
  651.  lea     dd_multicasts(a5),a0          ; New MinList for multicast filters
  652.  bsr     _newlist
  653.  
  654.  lea     dd_multicastssema(a5),a0
  655.  jsr     _LVOInitSemaphore(a6)
  656.  
  657.  lea     dd_rxint+ln_type(a5),a1
  658.  lea     rxintname(pc),a0
  659.  move.w  #(NT_INTERRUPT<<8)|16,(a1)+   ; priority 16
  660.  move.l  a0,(a1)+                      ; set up rx swi
  661.  lea     rxintcode(pc),a0
  662.  move.l  a5,(a1)+
  663.  move.l  a0,(a1)+
  664.  
  665.  lea     dd_txint+ln_type(a5),a1
  666.  lea     txintname(pc),a0
  667.  move.w  #(NT_INTERRUPT<<8)|0,(a1)+    ; priority 0
  668.  move.l  a0,(a1)+                      ; set up tx swi
  669.  lea     txintcode(pc),a0
  670.  move.l  a5,(a1)+
  671.  move.l  a0,(a1)+
  672.  
  673.  
  674.  
  675.  move.l  a4,dd_SegList(a5)   ; seglist for expunge
  676.  move.l  a6,exec_base        ; local copy of execbase
  677.  move.l  a5,me_myself        ; for speedup
  678.  
  679.  move.l  a5,d0
  680. .pop:
  681.  movem.l (sp)+,d1-d7/a0-a5
  682.  rts
  683.  
  684.  ifge    __CPU-68020
  685. .no020
  686.  bug     <"cnet: initRoutine failed, no 68020+ CPU",10>
  687.  bra.s   .err
  688.  endc
  689.  
  690. .no_cardres:
  691.  bug     <"cnet: initRoutine could not open card.resource",10>
  692.  bra     .err
  693.  
  694. .no_utility:
  695.  bug     <"cnet: initRoutine could not open utility.library V36",10>
  696.  
  697. .err:
  698. ; free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
  699.  moveq   #0,d0
  700.  move.l  a5,a1                        ; devicebase
  701.  move.w  lib_negsize(a5),d0
  702.  sub.l   d0,a1                        ; calculate base of functions
  703.  add.w   lib_possize(a5),d0           ; calculate size of functions + data area
  704.  jsr     _LVOFreeMem(a6)              ; must use FreeMem here!
  705.  
  706.  moveq   #0,d0
  707.  bra.s   .pop
  708.  
  709. .nopool:
  710.  bug     <"cnet: initRoutine could not create memory pool",10>
  711.  
  712.  lea     dd_timereq(a5),a1
  713.  jsr     _LVOCloseDevice(a6)
  714.  bra     .closeutil
  715.  
  716. .no_timerdev:
  717.  bug     <"cnet: initRoutine could open timer.device",10>
  718.  
  719. .closeutil:
  720.  move.l  dd_utilitybase(a5),a1
  721.  jsr     _LVOCloseLibrary(a6)
  722.  bra.s   .err
  723.  
  724.  
  725.  
  726.  
  727. _Null:
  728.  moveq   #0,d0
  729.  rts
  730.  
  731.  
  732.  
  733.  
  734. ;----------------------------------------------------------------------
  735. ;
  736. ; Here begins the system interface commands. When the user calls
  737. ; OpenDevice/CloseDevice/RemDevice, this eventually gets translated
  738. ; into a call to the following routines (Open_Device/Close_Device/
  739. ; Expunge_Device). Exec has already put our device pointer in a6 for
  740. ; us.
  741.  
  742.  
  743.  
  744. ;=================================================================
  745. ;              initialise standard list
  746. ;=================================================================
  747. ;
  748. ;   newlist(list)
  749. ;            a0
  750.  
  751. _newlist:
  752.  NEWLIST a0
  753.  rts
  754.  
  755.  
  756.  
  757. ;=================================================================
  758. ;                         Open Device
  759. ;=================================================================
  760. ;
  761. ; error = Open_Device(device, ioreq, unitnum, flags)
  762. ;  d0                   a6      a1     d0      d1
  763. ;
  764. ; Open sets the IO_ERROR field on an error. If it was successfull,
  765. ; we should also set up the IO_UNIT and LN_TYPE fields. Exec takes
  766. ; care of setting up IO_DEVICE.
  767. ;
  768. Open_Device:
  769. ;
  770. ;** Subtle point: any AllocMem() call can cause a call to this device's
  771. ;** expunge vector. If LIB_OPENCNT is zero, the device might get expunged.
  772. ;
  773.  addq.w  #1,lib_opencnt(a6)          ; Fake an opener for duration of call <|>
  774.  
  775.  ifnd    errordebonly
  776.  bug     <10,"cnet: OpenDevice(ioreq $%lx, unit %ld, flags $%02lx)",10>,a1,d0,d1
  777.  endc
  778.  
  779.  ifgt    0
  780.  ifd     debug
  781.  ifd     verbose
  782.  move.l  #100000,d0
  783. .wait:
  784.  tst.b   $bfe001
  785.  subq.l  #1,d0
  786.  bne.s   .wait
  787.  endc
  788.  endc
  789.  endc
  790.  
  791.  movem.l d2-d4/a2-a4/a6,-(sp)
  792.  move.l  a6,a3                       ; a3 = device
  793.  move.l  a1,a4                       ; a4 = ioreq
  794.  move.l  d0,d4                       ; d4 = unit
  795.  
  796.  cmp.w   #IOS2_SIZE,mn_length(a4)    ; reject invalid requests
  797.  blt     .badcaller
  798.  
  799.  btst    #DDB_MINE,dd_flags+1(a3)
  800.  bne     .isexclusive
  801.  
  802.  btst    #SANA2OPB_MINE,d1           ; want exclusive mode ?
  803.  beq.s   .init
  804.  
  805.  cmp.w   #1,lib_opencnt(a3)          ; must not be any other openers
  806.  bne     .isnonexcl
  807.  bset    #DDB_MINE,dd_flags+1(a3)    ; set exclusive mode
  808.  btst    #SANA2OPB_PROM,d1
  809.  beq.s   .init
  810.  bset    #DDB_PROM,dd_flags+1(a3)    ; set promiscuous mode
  811. .init:
  812.  
  813.  
  814.  move.l  a3,a0
  815.  move.l  a4,a1
  816.  move.l  d4,d0
  817.  bsr     Open_Unit                   ; open unit
  818.  move.l  d0,io_unit(a4)
  819.  beq     .openerr
  820.  
  821.  
  822.  btst    #DDB_NICUP,dd_flags+1(a3)   ; nic already initialised ?
  823.  bne.s   .nickdone
  824.  move.l  a3,a1
  825.  moveq   #0,d0
  826.  bsr     init_card                   ; init PCMCIA card
  827.  tst.l   d0
  828.  bne.s   .error
  829.  move.l  a3,a1
  830.  moveq   #0,d0
  831.  bsr     init_nic                    ; set up nic
  832.  tst.l   d0
  833.  bne.s   .error
  834. .nickdone:
  835.  
  836.  
  837.  btst    #DDB_OFFLINE,dd_flags+1(a3) ; previously put offline ?
  838.  bne.s   .opened
  839.  bset    #DDB_ONLINE,dd_flags+1(a3)  ; ready to accept packets
  840. .opened:
  841.  
  842.  
  843.  clr.b   io_error(a4)                ; IMPORTANT: Mark IORequest as "complete"
  844.  move.b  #NT_REPLYMSG,ln_type(a4)
  845.  addq.w  #1,lib_OpenCnt(a3)          ; opened successfully
  846.  bclr    #LIBB_DELEXP,lib_flags(a3)  ; prevent delayed expunges
  847.  
  848.  moveq   #0,d0
  849.  ifnd    errordebonly
  850.  bug     <"cnet: OpenDevice OK",10,10>
  851.  endc
  852.  
  853.  
  854. .done:
  855.  movem.l (sp)+,d2-d4/a2-a4/a6
  856.  subq.w  #1,lib_opencnt(a6)          ; ** End of expunge protection <|>
  857.  rts
  858.  
  859.  
  860.  
  861. .badcaller
  862.  bug     <"cnet: OpenDevice invalid MN_LENGTH!",10>
  863.  bra.s   .openerr
  864.  
  865. .isexclusive:
  866.  bug     <"cnet: device already in use exclusively!",10>
  867.  bra.s   .openerr
  868.  
  869. .isnonexcl:
  870.  bug     <"cnet: device already in use non-exclusively!",10>
  871.  bra.s   .openerr
  872.  
  873. .error:
  874.  bclr    #DDB_CARDHANDLE,dd_flags+1(a3)   ; test and clear - did we own card ?
  875.  beq.s   .nocard
  876.  
  877. ; now it's offline
  878.  and.w   #~DDF_ONLINE,dd_flags(a3)
  879.  
  880. ; kill the nic
  881.  bsr     kill_nic
  882.  
  883.  move.l  dd_cardres(a3),a6
  884.  lea     dd_cardhandle(a3),a1
  885.  moveq   #CARDF_REMOVEHANDLE,d0
  886.  jsr     _LVOReleaseCard(a6)         ; release card
  887. .nocard:
  888.  
  889.  
  890.  move.l  ios2_buffermanagement(a4),d0
  891.  beq.s   .nobufman                    ; got a buffermanagement pointer ?
  892.  clr.l   ios2_buffermanagement(a4)
  893.  
  894.  move.l  exec_base(pc),a6
  895.  
  896.  move.l  d0,a1
  897.  move.l  d0,a2
  898.  ifnd    errordebonly
  899.  bug     <"cnet: OpenDevice remove bufman at $%lx",10>,a1
  900.  endc
  901.  SOFTDISABLE                          ; lock access to list
  902.  REMOVE                               ; remove bufman struct from list
  903.  SOFTENABLE                           ; release lock on list
  904.  move.l  a2,a1
  905.  moveq   #bufman_sizeof,d0            ; discard buffer management struct
  906.  bsr     free
  907. .nobufman:
  908.  
  909.  
  910. .openerr:
  911.  moveq   #IOERR_OPENFAIL,d0          ; error, opendevice failed!
  912.  move.b  d0,io_error(a4)
  913.  move.l  d0,io_unit(a4)
  914.  move.l  d0,io_device(a4)            ; IMPORTANT: trash IO_DEVICE on open failure
  915.  bug     <"cnet: OpenDevice failed!",10,10>
  916.  bra.s   .done
  917.  
  918.  
  919.  
  920. ;===============================================================
  921. ;                 unit=Open Unit(device, ioreq, unitnum)
  922. ;                  d0              a0      a1     d0
  923. ;===============================================================
  924. ;
  925. ; Get the caller's buffer copy callback vectors
  926. ;
  927. Open_Unit:
  928.  ifnd    errordebonly
  929.  bug     <"cnet: Open_Unit(ioreq $%08lx) taglist: $%08lx",10>,a1,ios2_buffermanagement(a1)
  930.  endc
  931.  
  932.  movem.l d2-d6/a2-a5,-(sp)
  933.  move.l  a0,a4                    ; a4 = device
  934.  move.l  a1,a5                    ; a5 = ioreq
  935.  tst.l   d0                       ; only unit 0 is supported
  936.  bne     .error
  937.  
  938. ; If null taglist is supplied we don't fail!
  939.  
  940.  move.l  ios2_buffermanagement(a5),d0  ; tag list supplied?
  941.  beq     .ok
  942.  moveq   #0,d2                    ; d2 = tags found
  943.  move.l  d0,a2                    ; a2 = tag list
  944.  
  945. ; Note: I don't complain if I can't find pointers to the callback
  946. ; routines. This is because there are some programs that may need to
  947. ; open the device, but will never use any device commands that
  948. ; require the callbacks. Instead I check on CMD_READ, CMD_READORPHAN
  949. ; and CMD_WRITE for missing routines.
  950.  
  951.  move.l  exec_base(pc),a6
  952.  
  953.  moveq   #bufman_sizeof,d0        ; allocate memory for bufman vectors
  954.  bsr     alloc
  955.  move.l  d0,ios2_buffermanagement(a5)  ; return bufman node
  956.  beq     .error
  957.  
  958.  move.l  d0,a3
  959.  
  960.  move.l  dd_utilitybase(a4),a6
  961.  
  962.  ; get copyfrom functions:
  963.  
  964.  move.l  #S2_COPYFROMBUFF,d0
  965.  moveq   #0,d1
  966.  move.l  a2,a0
  967.  jsr     _LVOGetTagData(a6)
  968.  move.l  d0,bufman_copyfrombuf(a3)
  969.  
  970. ; This is new SANA-II V3 Addition
  971.  
  972.  move.l  #S2_DMACopyFromBuff32,d0
  973.  moveq   #0,d1
  974.  move.l  a2,a0
  975.  jsr     _LVOGetTagData(a6)
  976.  move.l  d0,bufman_dmacopyfrombuf32(a3)
  977.  
  978.  ifnd    errordebonly
  979.  bug     <"cnet: S2_DMACopyFromBuff32 = $%08lx",10>,d0
  980.  endc
  981.  
  982.  ; get copyto functions:
  983.  
  984.  move.l  #S2_COPYTOBUFF,d0
  985.  moveq   #0,d1
  986.  move.l  a2,a0
  987.  jsr     _LVOGetTagData(a6)
  988.  move.l  d0,bufman_copytobuf(a3)
  989.  
  990. ; This is new for SANA-II V3 Addition
  991.  
  992.  move.l  #S2_DMACopyToBuff32,d0
  993.  moveq   #0,d1
  994.  move.l  a2,a0
  995.  jsr     _LVOGetTagData(a6)
  996.  move.l  d0,bufman_dmacopytobuf32(a3)
  997.  
  998.  ifnd    errordebonly
  999.  bug     <"cnet: S2_DMACopyToBuff32 = $%08lx",10>,d0
  1000.  endc
  1001.  
  1002. ; And this is new SANA-II V2 Addition
  1003.  move.l  #S2_PACKETFILTER,d0
  1004.  moveq   #0,d1
  1005.  move.l  a2,a0
  1006.  jsr     _LVOGetTagData(a6)
  1007.  move.l  d0,bufman_packetfilter(a3)    ; if null everything get thru
  1008.  
  1009.  ifnd    errordebonly
  1010.  ifd     debug
  1011.  bug     <"cnet: S2_PacketFilter = $%08lx",10>,d0
  1012.  ifd     verbose
  1013.  tst.l   d0
  1014.  beq.s   .v1
  1015.  move.l  d0,a0
  1016.  bug     <"cnet: PacketFilter h_Entry = $%08lx h_SubEntry = $%08lx h_Data = $%08lx",10>,8(a0),12(a0),16(a0)
  1017. .v1:
  1018.  
  1019.  move.l  #S2_COPYFROMBUFF16,d0
  1020.  moveq   #0,d1
  1021.  move.l  a2,a0
  1022.  jsr     _LVOGetTagData(a6)
  1023.  bug     <"cnet: S2_CopyFromBuff16 = $%08lx",10>,d0
  1024.  
  1025.  move.l  #S2_COPYTOBUFF16,d0
  1026.  moveq   #0,d1
  1027.  move.l  a2,a0
  1028.  jsr     _LVOGetTagData(a6)
  1029.  bug     <"cnet: S2_CopyToBuff16 = $%08lx",10>,d0
  1030.  
  1031.  move.l  #S2_COPYFROMBUFF32,d0
  1032.  moveq   #0,d1
  1033.  move.l  a2,a0
  1034.  jsr     _LVOGetTagData(a6)
  1035.  bug     <"cnet: S2_CopyFromBuff32 = $%08lx",10>,d0
  1036.  
  1037.  move.l  #S2_COPYTOBUFF32,d0
  1038.  moveq   #0,d1
  1039.  move.l  a2,a0
  1040.  jsr     _LVOGetTagData(a6)
  1041.  bug     <"cnet: S2_CopyToBuff32 = $%08lx",10>,d0
  1042.  
  1043.  endc
  1044.  endc
  1045.  endc
  1046.  
  1047.  move.l  exec_base(pc),a6
  1048.  
  1049.  ; Init the list for CMD_READ requests
  1050.  lea     bufman_rxqueue(a3),a0
  1051.  bsr     _newlist
  1052.  
  1053.  ifnd    errordebonly
  1054.  bug     <"cnet: addbufman at $%lx",10>,a3
  1055.  endc
  1056.  lea     dd_bufmanlist(a4),a0
  1057.  move.l  a3,a1
  1058.  SOFTDISABLE                      ; lock access to list
  1059.  ADDHEAD                          ; add to buffer management list
  1060.  SOFTENABLE                       ; release lock on list
  1061.  bra.s   .ok
  1062.  
  1063. .error:
  1064.  moveq   #0,d0                    ; return error
  1065.  bra.s   .done
  1066.  
  1067. .ok:
  1068.  moveq   #1,d0                    ; return OK
  1069. .done:
  1070.  movem.l (sp)+,d2-d6/a2-a5
  1071.  rts
  1072.  
  1073.  
  1074.  
  1075. ;============================================================
  1076. ;                      Close Device
  1077. ;============================================================
  1078. ;
  1079. ;  Seglist = CloseDevice(ioreq, device)
  1080. ;    d0                    a1    a6
  1081. ;
  1082. ;
  1083. ; There are two different things that might be returned from the Close
  1084. ; routine. If the device wishes to be unloaded, then Close must return
  1085. ; the segment list (as given to Init). Otherwise close MUST return NULL.
  1086. ;
  1087. ;
  1088. Close_Device:
  1089.  ifnd    errordebonly
  1090.  bug     <10,"cnet: CloseDevice(ioreq $%08lx)",10>,a1
  1091.  endc
  1092.  
  1093.  ifgt    0
  1094.  ifd     debug
  1095.  ifd     verbose
  1096.  move.l  #100000,d0
  1097. .wait:
  1098.  tst.b   $bfe001
  1099.  subq.l  #1,d0
  1100.  bne.s   .wait
  1101.  endc
  1102.  endc
  1103.  endc
  1104.  
  1105.  movem.l a2-a4/a6,-(sp)
  1106.  move.l  a1,a3                        ; a3 = ioreq
  1107.  move.l  a6,a4                        ; a4 = device
  1108.  
  1109.  moveq   #0,d0                        ; default: no unload
  1110.  tst.w   lib_OpenCnt(a4)
  1111.  beq     .done                        ; invalid state!
  1112.  
  1113.  move.l  exec_base(pc),a6
  1114.  
  1115.  moveq   #-1,d0
  1116.  move.l  d0,io_unit(a3)               ; We're closed...
  1117.  move.l  d0,io_device(a3)             ; customers not welcome at this IORequest!!
  1118.  
  1119.  move.l  ios2_buffermanagement(a3),d0
  1120.  beq.s   .nobufman                    ; got a buffermanagement pointer ?
  1121.  clr.l   ios2_buffermanagement(a3)
  1122.  
  1123.  move.l  d0,a1
  1124.  move.l  d0,a2
  1125.  ifnd    errordebonly
  1126.  bug     <"cnet: remove bufman at $%lx",10>,a1
  1127.  endc
  1128.  
  1129.  SOFTDISABLE                          ; lock access to list
  1130.  REMOVE                               ; remove bufman struct from list
  1131.  SOFTENABLE                           ; release lock on list
  1132.  
  1133.  move.l  a2,a1
  1134.  moveq   #bufman_sizeof,d0            ; discard buffer management struct
  1135.  bsr     free
  1136. .nobufman:
  1137.  
  1138.  
  1139.  moveq   #0,d0                        ; default: no unload
  1140.  subq.w  #1,lib_OpenCnt(a4)           ; one less opener
  1141.  bne.s   .done                        ; still open ?
  1142.  
  1143.  ifnd    errordebonly
  1144.  bug     <"cnet: devclosedown",10>
  1145.  endc
  1146.  
  1147. ; close down the devive
  1148.  move.l  a4,a1
  1149. ; a6 = execbase
  1150.  bsr     devclosedown
  1151.  
  1152.  moveq   #0,d0                        ; default: no unload
  1153.  btst    #LIBB_DELEXP,lib_flags(a4)
  1154.  beq.s   .done                        ; delayed expunge pending ?
  1155.  
  1156. ;  do the expunge
  1157.  ifnd    errordebonly
  1158.  bug     <"cnet: LIBF_DELEXP calling Expunge!",10>
  1159.  endc
  1160.  move.l  a4,a6
  1161.  bsr.s   Expunge_Device
  1162.  
  1163. .done:
  1164.  movem.l (sp)+,a2-a4/a6
  1165.  ifnd    errordebonly
  1166.  bug     <"cnet: CloseDevice return: $%08lx",10,10>,d0
  1167.  endc
  1168.  rts                                  ; MUST return either zero or the SegList!!!
  1169.  
  1170.  
  1171.  
  1172. ;============================================================
  1173. ;                      Expunge Device
  1174. ;============================================================
  1175. ;
  1176. ;  Seglist = ExpungeDevice(device)
  1177. ;    d0                      a6
  1178. ;
  1179. ; Expunge is called by the memory allocator when the system is low on
  1180. ; memory (or by us from the CloseDevice above!).
  1181. ;
  1182. ; There are two different things that might be returned from the Expunge
  1183. ; routine.  If the device is no longer open then Expunge may return the
  1184. ; segment list (as given to Init). Otherwise Expunge may set the delayed
  1185. ; expunge flag and return NULL.
  1186. ;
  1187. ; One other important note: because Expunge is called from the memory
  1188. ; allocator, it may NEVER Wait() or otherwise take long time to complete.
  1189. ;
  1190. ;
  1191. Expunge_Device:
  1192.  ifnd    errordebonly
  1193.  bug     <10,"cnet: Expunge_Device $%08lx",10>,a6
  1194.  endc
  1195.  
  1196.  ifgt    0
  1197.  ifd     debug
  1198.  ifd     verbose
  1199.  move.l  #100000,d0
  1200. .wait:
  1201.  tst.b   $bfe001
  1202.  subq.l  #1,d0
  1203.  bne.s   .wait
  1204.  endc
  1205.  endc
  1206.  endc
  1207.  
  1208.  tst.w   lib_opencnt(a6)
  1209.  beq.s   .unload                      ; anyone has us open ?
  1210.  
  1211. ; it is still open. set the delayed expunge flag
  1212.  
  1213.  ifnd    errordebonly
  1214.  bug     <"cnet: Could not expunge, LIBF_DELEXP set!",10>
  1215.  endc
  1216.  bset    #LIBB_DELEXP,lib_flags(a6)
  1217.  moveq   #0,d0                        ; do not unload the seg
  1218.  rts
  1219.  
  1220.  
  1221. .unload
  1222.  ifnd    errordebonly
  1223.  bug     <"cnet: Unloading...",10>
  1224.  endc
  1225.  
  1226.  movem.l a4/a6,-(sp)
  1227.  move.l  dd_SegList(a6),-(sp)         ; seglist to return in d0
  1228.  
  1229.  move.l  a6,a4
  1230.  move.l  exec_base(pc),a6
  1231.  
  1232. ; put the hardware offline
  1233.  move.l  a4,a1
  1234. ; a6=execbase
  1235.  ifnd    errordebonly
  1236.  bug     <"cnet: devclosedown",10>
  1237.  endc
  1238.  bsr     devclosedown
  1239.  
  1240.  
  1241. ; release the card, if we own it.
  1242.  bclr    #DDB_CARDHANDLE,dd_flags+1(a4)   ; test and clear - did we own card ?
  1243.  beq.s   .nocard
  1244.  move.l  a6,-(sp)
  1245.  move.l  dd_cardres(a4),a6
  1246.  lea     dd_cardhandle(a4),a1
  1247.  moveq   #CARDF_REMOVEHANDLE,d0
  1248.  ifnd    errordebonly
  1249.  bug     <"cnet: releasing cardhandle $%08lx",10>,a1
  1250.  endc
  1251.  jsr     _LVOReleaseCard(a6)         ; release card
  1252.  move.l  (sp)+,a6
  1253. .nocard:
  1254.  
  1255.  
  1256. ; free memorypool
  1257.  move.l  poolptr(pc),a0
  1258.  ifnd    errordebonly
  1259.  bug     <"cnet: freeing memorypool $%08lx",10>,a0
  1260.  endc
  1261.  bsr     deletepool
  1262.  
  1263.  
  1264. ; close timer.device
  1265.  lea     dd_timereq(a4),a1
  1266.  ifnd    errordebonly
  1267.  bug     <"cnet: closedevice timer ior $%08lx",10>,a1
  1268.  endc
  1269.  jsr     _LVOCloseDevice(a6)
  1270.  
  1271.  
  1272. ; close utilitybase
  1273.  move.l  dd_utilitybase(a4),a1
  1274.  ifnd    errordebonly
  1275.  bug     <"cnet: closing utilitybase $%08lx",10>,a1
  1276.  endc
  1277.  jsr     _LVOCloseLibrary(a6)
  1278.  
  1279.  
  1280. ; there is no CloseResource() call.
  1281.  
  1282.  
  1283.  ; unlink from device list
  1284.  move.l  a4,a1
  1285.  ifnd    errordebonly
  1286.  bug     <"cnet: removing device node $%08lx",10>,a1
  1287.  endc
  1288.  REMOVE
  1289.  
  1290.  
  1291. ; free our memory (must calculate from LIB_POSSIZE & LIB_NEGSIZE)
  1292.  moveq   #0,d0
  1293.  move.l  a4,a1                        ; devicebase
  1294.  move.w  lib_negsize(a4),d0
  1295.  sub.l   d0,a1                        ; calculate base of functions
  1296.  add.w   lib_possize(a4),d0           ; calculate size of functions + data area
  1297.  jsr     _LVOFreeMem(a6)              ; must use FreeMem here!
  1298.  
  1299.  ifnd    errordebonly
  1300.  bug     <"cnet: Unload done! cnet.device expunged!",10,10>
  1301.  endc
  1302.  
  1303.  movem.l (sp)+,d0/a4/a6               ; pop regs and seglist pointer
  1304.  rts
  1305.  
  1306.  
  1307.  
  1308. ;======================================================================
  1309. ;                  devclosedown(device, execbase)
  1310. ;                                a1       a6
  1311. ;======================================================================
  1312. ;
  1313. ; Put the nic into sleep... also do whatever nececcary hw magic
  1314. ; before device closedown. mark the device offline and unconfigured.
  1315. ;
  1316. devclosedown:
  1317.  ; not online, cancel exclusive mode, cancel promiscuous mode
  1318.  and.w   #~(DDF_ONLINE|DDF_MINE|DDF_PROM),dd_flags(a1)
  1319.  bra     kill_nic                                   ; stop controller
  1320.  
  1321.  
  1322.  
  1323. ;===============================================================
  1324. ;                       Dev_BeginIO
  1325. ;===============================================================
  1326. ; the entry point for all device commands
  1327. ;
  1328.  
  1329.  CNOP 0,4
  1330.  
  1331. _DevBeginIO:
  1332.  move.w  io_command(a1),d0       ; get command number
  1333.  move.b  #NT_MESSAGE,ln_type(a1) ; make sure type is message
  1334.  cmp.w   #S2_END,d0
  1335.  bhs     .berror                 ; valid table command?
  1336.  ifge    __CPU-68020
  1337.  move.l  .cmds(pc,d0.w*4),d0      ; get command vector (020+)
  1338.  else
  1339.  lsl.w   #2,d0
  1340.  move.l  .cmds(pc,d0.w),d0        ; get command vector
  1341.  endc
  1342.  bne.s   .ok
  1343. .error:
  1344.  move.b  #IOERR_NOCMD,io_error(a1)
  1345.  bra     TermIO                  ; return invalid command
  1346. .ok:
  1347.  move.l  d0,a0
  1348.  clr.b   io_error(a1)            ; no errors yet
  1349.  
  1350.  ifgt    0
  1351.  ifnd    errordebonly
  1352.  ifd     debug
  1353.  ifd     verbose
  1354.  moveq   #0,d0
  1355.  move.w  io_command(a1),d0
  1356.  bug <"cnet: BeginIO ioreq $%08lx cmd %ld",10>,a1,d0
  1357.  move.l  #300000,d0
  1358. .wait:
  1359.  tst.b   $bfe001
  1360.  subq.l  #1,d0
  1361.  bne.s   .wait
  1362.  endc
  1363.  endc
  1364.  endc
  1365.  endc
  1366.  
  1367.  jmp     (a0)                    ; jump to command
  1368.  
  1369.  
  1370. ; command vectors
  1371.  
  1372.  CNOP 0,4
  1373.  
  1374. .cmds:
  1375.  dc.l    0                           ;  0
  1376.  dc.l    0                           ;  1
  1377.  dc.l    devcmd_read                 ;  2 = cmd_read
  1378.  dc.l    devcmd_write                ;  3 = cmd_write
  1379.  dc.l    0                           ;  4
  1380.  dc.l    0                           ;  5
  1381.  dc.l    0                           ;  6
  1382.  dc.l    0                           ;  7
  1383.  dc.l    devcmd_flush                ;  8 = cmd_flush
  1384.  dc.l    devcmd_devicequery          ;  9 = S2_DEVICEQUERY
  1385.  dc.l    devcmd_getstationaddress    ;  10= S2_GETSTATIONADDRESS
  1386.  dc.l    devcmd_configinterface      ;  11= S2_CONFIGINTERFACE
  1387.  dc.l    0                           ;  12
  1388.  dc.l    0                           ;  13
  1389.  dc.l    devcmd_addmulticast         ;  14= S2_ADDMULTICASTADDRESS
  1390.  dc.l    devcmd_delmulticast         ;  15= S2_DELMULTICASTADDRESS
  1391.  dc.l    devcmd_multicast            ;  16= S2_MULTICAST
  1392.  dc.l    devcmd_broadcast            ;  17= S2_BROADCAST
  1393.  dc.l    devcmd_tracktype            ;  18= S2_TRACKTYPE
  1394.  dc.l    devcmd_untracktype          ;  19= S2_UNTRACKTYPE
  1395.  dc.l    devcmd_gettypestats         ;  20= S2_GETTYPESTATS
  1396.  dc.l    devcmd_getspecialstats      ;  21= S2_GETSPECIALSTATS
  1397.  dc.l    devcmd_getglobalstats       ;  22= S2_GETGLOBALSTATS
  1398.  dc.l    devcmd_onevent              ;  23= S2_ONEVENT
  1399.  dc.l    devcmd_readorphan           ;  24= S2_READORPHAN
  1400.  dc.l    devcmd_online               ;  25= S2_ONLINE
  1401.  dc.l    devcmd_offline              ;  26= S2_OFFLINE
  1402.  
  1403. .nsd_supported:
  1404.  dc.w    2,3
  1405.  dc.w    8,9,10,11
  1406.  dc.w    14,15,16,17,18,19,20,21,22,23,24,25,26
  1407.  dc.w    NSCMD_DEVICEQUERY
  1408.  dc.w    S2_ADDMULTICASTADDRESSES
  1409.  dc.w    S2_DELMULTICASTADDRESSES
  1410.  dc.w    0
  1411.  
  1412. .berror:
  1413.  clr.b   io_error(a1)                ; no error
  1414.  cmp.w   #S2_ADDMULTICASTADDRESSES,d0
  1415.  beq     devcmd_addmulticasts
  1416.  cmp.w   #S2_DELMULTICASTADDRESSES,d0
  1417.  beq     devcmd_delmulticasts
  1418.  
  1419.  cmp.w   #NSCMD_DEVICEQUERY,d0       ; is it NSCMD_DEVICEQUERY?
  1420.  bne     .error
  1421.  
  1422.  ifnd    errordebonly
  1423.  ifd     verbose
  1424.  bug     <"cnet: NSCMD_DEVICEQUERY ior $%08lx",10>,a1
  1425.  endc
  1426.  endc
  1427.  cmp.l   #16,io_length(a1)
  1428.  blt     .error
  1429.  move.l  io_data(a1),d0
  1430.  beq     .error
  1431.  move.l  d0,a0
  1432.  tst.l   (a0)+
  1433.  bne     .error
  1434.  tst.l   (a0)
  1435.  bne     .error
  1436.  
  1437.  ifnd    errordebonly
  1438.  ifd     verbose
  1439.  bug     <"cnet: replied with NSDEVTYPE_SANA2!",10>
  1440.  endc
  1441.  endc
  1442.  moveq   #16,d0
  1443.  move.l  d0,(a0)+
  1444.  move.l  #$00070000,(a0)+            ; NSDEVTYPE_SANA2<<16
  1445.  move.l  #.nsd_supported,(a0)
  1446.  move.l  d0,io_actual(a1)
  1447.  bra     TermIO
  1448.  
  1449.  
  1450.  
  1451. ;====================================================================
  1452. ;                              Abort_IO
  1453. ;====================================================================
  1454. ;
  1455. ;                   try to cancel a pending ioreq
  1456. ;
  1457. _DevAbortIO:
  1458.  
  1459.  ifnd    errordebonly
  1460.  bug <"cnet: AbortIO ioreq $%08lx",10>,a1
  1461.  endc
  1462.  
  1463.  movem.l d2/a2-a4/a6,-(sp)
  1464.  move.l  a6,a4                            ; a4=device
  1465.  move.l  exec_base(pc),a6
  1466.  move.l  a1,a2                            ; a2=ioreq
  1467.  
  1468.  moveq   #0,d0                            ; if already replied silentry ignore
  1469.  SOFTDISABLE                              ; lock access to lists
  1470.  cmp.b   #NT_MESSAGE,ln_type(a2)          ; only cancel queued ioreq's
  1471.  bne.s   .done
  1472.  
  1473.  move.w  io_command(a2),d0
  1474.  cmp.w   #CMD_READ,d0
  1475.  beq.s   .read
  1476.  
  1477.  lea     dd_orphanlist(a4),a0
  1478.  cmp.w   #S2_READORPHAN,d0
  1479.  beq.s   .thisone
  1480.  
  1481.  lea     dd_writelist(a4),a0
  1482.  cmp.w   #CMD_WRITE,d0
  1483.  beq.s   .thisone
  1484.  cmp.w   #S2_MULTICAST,d0
  1485.  beq.s   .thisone
  1486.  cmp.w   #S2_BROADCAST,d0
  1487.  beq.s   .thisone
  1488.  
  1489.  lea     dd_eventlist(a4),a0
  1490.  cmp.w   #S2_ONEVENT,d0
  1491.  beq.s   .thisone
  1492.  
  1493.  bug <"cnet: AbortIO not READ, READORPHAN, WRITE, MULTICAST, BROADCAST or ONEVENT",10>
  1494.  moveq   #IOERR_NOCMD,d0
  1495.  bra.s   .done
  1496.  
  1497. .read:
  1498. ; Check all nodes in dd_bufmanlist until we succeed to abort:
  1499. ; if we can't find the ioreq in any list, return IOERR_NOCMD.
  1500.  
  1501.  move.l  dd_bufmanlist(a4),a3
  1502.  ifnd    errordebonly
  1503. ;bug <"cnet: AbortIO READ bufmanlist 1st: $%08lx",10>,a3
  1504.  endc
  1505. .readhandle
  1506.  moveq   #IOERR_NOCMD,d0                  ; return failure if we can't find it
  1507.  move.l  (a3),d2
  1508.  beq.s   .done                            ; end of list?
  1509.  lea     bufman_rxqueue(a3),a0
  1510.  ; a2=ioreq
  1511.  bsr     AbortReq
  1512.  tst.l   d0
  1513.  beq.s   .done                            ; succeeded to abort?
  1514.  move.l  d2,a3
  1515.  bra.s   .readhandle
  1516.  
  1517. .thisone:
  1518.  ; a0=list where the ioreqs should be in
  1519.  ; a2=ioreq
  1520.  bsr     AbortReq
  1521.  
  1522. .done:
  1523.  SOFTENABLE                               ; release lock on lists
  1524.  
  1525.  movem.l (sp)+,d2/a2-a4/a6
  1526.  rts
  1527.  
  1528.  
  1529.  
  1530. ;======================================================================
  1531. ;                  AbortReq(minlist, ioreq, execbase)
  1532. ;                             a0      a2      a6
  1533. ;======================================================================
  1534. ;
  1535. ; locate an IO request in a linked list and abort it if found.
  1536. ;
  1537. AbortReq:
  1538.  moveq   #IOERR_NOCMD,d0
  1539.  
  1540.  move.l  (a0),a0
  1541. .search:
  1542.  move.l  (a0),d1
  1543.  beq.s   .done                            ; end of list ?
  1544.  cmp.l   a2,a0                            ; = ioreq ?
  1545.  move.l  d1,a0                            ; note: movea doesn't change ccs!
  1546.  bne.s   .search
  1547.  
  1548.  move.l  a2,a1
  1549.  ifnd    errordebonly
  1550. ;bug <"cnet: AbortReq aborted $%08lx",10>,a1
  1551.  endc
  1552.  REMOVE                                   ; remove ioreq from list
  1553.  move.b  #NT_REPLYMSG,ln_type(a2)
  1554.  move.b  #IOERR_ABORTED,io_error(a2)
  1555.  move.l  a2,a1
  1556.  jsr     _LVOReplyMsg(a6)                 ; reply to originator's message
  1557.  moveq   #0,d0                            ; aborted OK
  1558. .done:
  1559.  rts
  1560.  
  1561.  
  1562.  
  1563. ;===========================================================
  1564. ;                      termio(ioreq)
  1565. ;                               a1
  1566. ;===========================================================
  1567. ;
  1568. ; return completed ioreq to sender.
  1569. ;
  1570. TermIO:
  1571.  move.b  #NT_REPLYMSG,ln_type(a1)
  1572.  btst    #IOB_QUICK,io_flags(a1)
  1573.  bne.s   .done                       ; does sender need a reply ?
  1574.  move.l  a6,-(sp)
  1575.  move.l  exec_base(pc),a6
  1576.  jsr     _LVOReplyMsg(a6)            ; send reply
  1577.  move.l  (sp)+,a6
  1578. .done:
  1579.  rts
  1580.  
  1581.  
  1582.  
  1583. ;====================================================
  1584. ;                     CMD_READ
  1585. ;====================================================
  1586. ;
  1587. ; if card is configured and online
  1588. ;
  1589.  CNOP 0,4
  1590. devcmd_read:
  1591.  ifd  verbose
  1592.  ifnd    errordebonly
  1593.  bug  <"cnet: cmd_read(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1594.  endc
  1595.  endc
  1596.  
  1597.  movem.l a2/a3/a6,-(sp)
  1598.  move.l  a1,a2                           ; a2 = ioreq
  1599.  move.l  io_device(a1),a3                ; a3 = device
  1600.  
  1601.  btst    #DDB_CONFIGURED,dd_flags+1(a3)  ; configured ?
  1602.  beq     .unconfigured
  1603.  btst    #DDB_ONLINE,dd_flags+1(a3)      ; online ?
  1604.  beq     .offline
  1605.  
  1606.  move.l  ios2_buffermanagement(a2),d0
  1607.  beq     .bad                            ; eeeekh, no bufman ?
  1608.  move.l  d0,a0
  1609.  tst.l   bufman_copytobuf(a0)
  1610.  beq     .bad                            ; this is needed for reading.. :)
  1611.  
  1612.  bclr    #IOB_QUICK,io_flags(a2)         ; must be queued
  1613.  move.l  exec_base(pc),a6
  1614.  
  1615. ; add to this ioreq's bufman_rxqueue
  1616.  
  1617.  lea     bufman_rxqueue(a0),a0
  1618.  move.l  a2,a1
  1619.  ifnd    errordebonly
  1620.  ifd     verbose
  1621.  bug     <"cnet: CMD_READ ior $%08lx added to bufman_rxqueue $%08lx",10>,a1,a0
  1622.  endc
  1623.  endc
  1624.  SOFTDISABLE
  1625.  ADDTAIL                                 ; add ioreq to read queue
  1626.  SOFTENABLE
  1627.  
  1628. .done:
  1629.  movem.l (sp)+,a2/a3/a6
  1630.  rts
  1631.  
  1632. .unconfigured:
  1633.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  1634.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1635.  bra.s   .error
  1636.  
  1637. .offline:
  1638.  moveq   #S2WERR_UNIT_OFFLINE,d0         ; error, device is offline
  1639.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1640.  bra.s   .error
  1641.  
  1642. .bad:
  1643.  moveq   #S2WERR_GENERIC_ERROR,d0        ; error, bad argument
  1644.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1645.  
  1646. .error:
  1647.  ifd     verbose
  1648.  bug     <"cnet: read ior $%08lx error %ld",10>,a2,d0
  1649.  endc
  1650.  
  1651.  move.l  d0,ios2_wireerror(a2)
  1652.  move.l  a2,a1
  1653.  bsr     TermIO
  1654.  bra.s   .done
  1655.  
  1656.  
  1657.  
  1658. ;====================================================
  1659. ;                     S2_READORPHAN
  1660. ;====================================================
  1661. ;
  1662. ; if card is configured and online
  1663. ;
  1664.  CNOP 0,4
  1665. devcmd_readorphan:
  1666.  ifnd    errordebonly
  1667.  bug     <"cnet: readorphan(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1668.  endc
  1669.  
  1670.  movem.l a2/a3/a6,-(sp)
  1671.  move.l  a1,a2                           ; a2 = ioreq
  1672.  move.l  io_device(a1),a3
  1673.  
  1674.  btst    #DDB_CONFIGURED,dd_flags+1(a3)  ; configured ?
  1675.  beq     .unconfigured
  1676.  btst    #DDB_ONLINE,dd_flags+1(a3)      ; online ?
  1677.  beq     .offline
  1678.  
  1679.  move.l  ios2_buffermanagement(a2),d0
  1680.  beq.s   .bad                            ; eeeekh, no bufman ?
  1681.  move.l  d0,a0
  1682.  tst.l   bufman_copytobuf(a0)
  1683.  beq.s   .bad                            ; this is needed for reading.. :)
  1684.  
  1685.  bclr    #IOB_QUICK,io_flags(a2)         ; must be queued
  1686.  move.l  exec_base(pc),a6
  1687.  lea     dd_orphanlist(a3),a0
  1688.  move.l  a2,a1
  1689.  ifnd    errordebonly
  1690.  bug     <"cnet: S2_READORPHAN ior $%08lx added to orphanlist $%08lx",10>,a1,a0
  1691.  endc
  1692.  SOFTDISABLE
  1693.  ADDTAIL                                 ; add ioreq to orphan queue
  1694.  SOFTENABLE
  1695.  
  1696. .done:
  1697.  movem.l (sp)+,a2/a3/a6
  1698.  rts
  1699.  
  1700. .unconfigured:
  1701.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  1702.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1703.  bra.s   .error
  1704.  
  1705. .offline:
  1706.  moveq   #S2WERR_UNIT_OFFLINE,d0         ; error, device is offline
  1707.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1708.  bra.s   .error
  1709.  
  1710. .bad:
  1711.  moveq   #S2WERR_GENERIC_ERROR,d0        ; error, bad argument
  1712.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1713.  
  1714. .error:
  1715.  ifd     verbose
  1716.  bug     <"cnet: readorphan ior $%08lx error %ld",10>,a2,d0
  1717.  endc
  1718.  
  1719.  move.l  d0,ios2_wireerror(a2)
  1720.  move.l  a2,a1
  1721.  bsr     TermIO
  1722.  bra.s   .done
  1723.  
  1724.  
  1725.  
  1726. ;======================================================
  1727. ;                      CMD_WRITE
  1728. ;======================================================
  1729. ;
  1730. ; if card is configured and online
  1731. ;
  1732.  CNOP 0,4
  1733. devcmd_write:
  1734.  ifnd    errordebonly
  1735.  ifd  verbose
  1736.  bug  <"cnet: cmd_write(ior $%08lx, type %ld)",10>,a1,ios2_packettype(a1)
  1737.  endc
  1738.  endc
  1739.  
  1740.  movem.l a2/a3/a6,-(sp)
  1741.  move.l  a1,a2                            ; a2 = ioreq
  1742.  move.l  io_device(a1),a3                 ; a3 = device
  1743.  
  1744.  btst    #DDB_CONFIGURED,dd_flags+1(a3)   ; configured ?
  1745.  beq     .unconfigured
  1746.  btst    #DDB_ONLINE,dd_flags+1(a3)       ; online ?
  1747.  beq     .offline
  1748.  
  1749. ; check ioreq's bufman validity
  1750.  
  1751.  move.l  ios2_buffermanagement(a2),d0
  1752.  beq     .bad                             ; eeeekh, no bufman ?
  1753.  move.l  d0,a0
  1754.  tst.l   bufman_copyfrombuf(a0)
  1755.  beq     .bad                             ; no routine for writing ?
  1756.  
  1757.  move.l  ios2_DataLength(a2),d1
  1758.  tst.b   io_flags(a2)                     ; (test SANA2IOB_RAW) raw packets ?
  1759.  bpl.s   .cooked
  1760.  
  1761.  cmp.l   #RAWPKT_SIZE,d1
  1762.  bls.s   .goodlen                         ; check packet size
  1763.  bra.s   .toobig
  1764.  
  1765. .cooked:
  1766.  cmp.l   #ETHERPKT_SIZE,d1
  1767.  bhi.s   .toobig
  1768.  
  1769. .goodlen:
  1770.  bclr    #IOB_QUICK,io_flags(a2)          ; must be queued
  1771.  move.l  exec_base(pc),a6
  1772.  lea     dd_writelist(a3),a0
  1773.  move.l  a2,a1
  1774.  ifnd    errordebonly
  1775.  ifd     verbose
  1776.  bug     <"cnet: CMD_WRITE ior $%08lx added to writelist $%08lx",10>,a1,a0
  1777.  endc
  1778.  endc
  1779.  SOFTDISABLE
  1780.  ADDTAIL                                  ; add ioreq to write queue
  1781.  SOFTENABLE
  1782.  
  1783.  ifd     nosendthrottle
  1784.  btst    #DDB_TX,dd_flags+1(a3)           ; if trasmit is currently in progress
  1785.  bne.s   .done                            ; don't bother triggering the interrupt
  1786.  endc
  1787.  
  1788.  lea     dd_txint(a3),a1
  1789.  jsr     _LVOCause(a6)                    ; start tx
  1790.  
  1791. .done:
  1792.  movem.l (sp)+,a2/a3/a6
  1793.  rts
  1794.  
  1795.  
  1796. .unconfigured:
  1797.  moveq   #S2WERR_NOT_CONFIGURED,d0        ; error, not configured
  1798.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  1799.  bra.s   .error
  1800.  
  1801. .offline:
  1802.  moveq   #S2WERR_UNIT_OFFLINE,d0          ; error, device is offline
  1803.  move.b  #S2ERR_OUTOFSERVICE,io_error(a2)
  1804.  bra.s   .error
  1805.  
  1806. .bad:
  1807.  moveq   #S2WERR_GENERIC_ERROR,d0         ; error, bad argument
  1808.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a2)
  1809.  bra.s   .error
  1810.  
  1811. .toobig:
  1812.  moveq   #S2EVENT_TX,d0                   ; return any TX events
  1813.  bsr     DoEvent
  1814.  moveq   #0,d0
  1815.  move.b  #S2ERR_MTU_EXCEEDED,io_error(a2) ; oops! packet too big
  1816.  
  1817. .error:
  1818.  ifd     verbose
  1819.  bug     <"cnet: write ior $%08lx error %ld",10>,a2,d0
  1820.  endc
  1821.  
  1822.  move.l  d0,ios2_wireerror(a2)
  1823.  move.l  a2,a1
  1824.  bsr     TermIO
  1825.  bra.s   .done
  1826.  
  1827.  
  1828.  
  1829. ;==============================================
  1830. ;                CMD_FLUSH
  1831. ;==============================================
  1832. ;
  1833. devcmd_flush:
  1834.  movem.l a1-a2/a6,-(sp)
  1835.  move.l  exec_base(pc),a6
  1836.  move.l  io_device(a1),a2             ; a2 = device
  1837.  
  1838.  ifnd    errordebonly
  1839.  bug     <"cnet: CMD_FLUSH ior $%08lx device $%08lx",10>,a1,a2
  1840.  endc
  1841.  
  1842.  ifgt    0
  1843.  ifd     debug
  1844.  ifd     verbose
  1845.  bug <"cnet: delaying...",10>
  1846.  move.l  #500000,d0
  1847. .wait:
  1848.  tst.b   $bfe001
  1849.  subq.l  #1,d0
  1850.  bne.s   .wait
  1851.  endc
  1852.  endc
  1853.  endc
  1854.  
  1855.  SOFTDISABLE
  1856.  
  1857.  move.l  a2,a0
  1858.  moveq   #IOERR_ABORTED,d0
  1859.  moveq   #0,d1
  1860.  bsr     AbortRW
  1861.  
  1862.  lea     dd_eventlist(a2),a0          ; abort all Event requests
  1863.  moveq   #IOERR_ABORTED,d0
  1864.  moveq   #0,d1
  1865.  bsr     AbortList
  1866.  
  1867.  SOFTENABLE
  1868.  ifnd    errordebonly
  1869.  bug     <"cnet: CMD_FLUSH done",10>
  1870.  endc
  1871.  
  1872.  movem.l (sp)+,a1-a2/a6
  1873.  bra     TermIO
  1874.  
  1875.  
  1876.  
  1877. ;======================================================================
  1878. ;                  abortlist(list, errcode, wireerror, execbase)
  1879. ;                             a0     d0.b      d1.l      a6
  1880. ;======================================================================
  1881. ;
  1882. ; Aborts all ios2requs in given list with ios2_Error set to errcode
  1883. ; and ios2_wireerror set to wireerror.
  1884. ;
  1885. AbortList:
  1886.  movem.l d2-d3/a2,-(sp)
  1887.  move.l  a0,a2
  1888.  move.b  d0,d2
  1889.  move.l  d1,d3
  1890.  bra.s   .flush
  1891.  
  1892. .loop:
  1893.  move.l  d0,a1
  1894. ;move.b  #NT_REPLYMSG,ln_type(a1)     ; DON'T!
  1895.  move.b  d2,io_error(a1)
  1896.  move.l  d3,ios2_wireerror(a1)
  1897.  ifnd    errordebonly
  1898. ;bug     <"cnet: AbortList ior $%08lx",10>,a1
  1899.  endc
  1900.  jsr     _LVOReplyMsg(a6)
  1901. .flush:
  1902.  move.l  a2,a0
  1903.  MYREMHEAD
  1904.  bne.s   .loop
  1905.  
  1906.  movem.l (sp)+,d2-d3/a2
  1907.  rts
  1908.  
  1909.  
  1910.  
  1911. ;======================================================================
  1912. ;                  abortrw(device, errcode, wireerror, execbase)
  1913. ;                            a0      d0.b      d1.l      a6
  1914. ;======================================================================
  1915. ;
  1916. ; Aborts all pending reads and writes with ios2_Error set to errcode
  1917. ; and ios2_wireerror set to wireerror.
  1918. ;
  1919. AbortRW:
  1920.  movem.l d2-d4/a2-a3,-(sp)
  1921.  move.l  a0,a3
  1922.  move.b  d0,d2
  1923.  move.l  d1,d3
  1924.  
  1925.  move.l  dd_bufmanlist(a3),a2
  1926. .reado:
  1927.  move.l  (a2),d4
  1928.  beq.s   .flushrest
  1929.  bra.s   .flushreads
  1930.  
  1931. .readloop:
  1932.  move.l  d0,a1
  1933. ;move.b  #NT_REPLYMSG,ln_type(a1)     ; DON'T!
  1934.  move.b  d2,io_error(a1)
  1935.  move.l  d3,ios2_wireerror(a1)
  1936.  ifnd    errordebonly
  1937. ;bug     <"cnet: AbortRead ior $%08lx",10>,a1
  1938.  endc
  1939.  jsr     _LVOReplyMsg(a6)             ; abort all Read requests
  1940. .flushreads:
  1941.  lea     bufman_rxqueue(a2),a0
  1942.  MYREMHEAD
  1943.  bne.s   .readloop
  1944.  
  1945.  move.l  d4,a2
  1946.  bra.s   .reado
  1947. .flushrest:
  1948.  
  1949.  lea     dd_orphanlist(a3),a0         ; abort all ReadOrphan requests
  1950.  move.b  d2,d0
  1951.  move.l  d3,d1
  1952.  bsr     AbortList
  1953.  
  1954.  lea     dd_writelist(a3),a0          ; abort all Write requests
  1955.  move.b  d2,d0
  1956.  move.l  d3,d1
  1957.  bsr     AbortList
  1958.  
  1959.  movem.l (sp)+,d2-d4/a2-a3
  1960.  rts
  1961.  
  1962.  
  1963.  
  1964. ;==============================================
  1965. ;               S2_ONLINE
  1966. ;==============================================
  1967. ;
  1968. ;         Try to put device online
  1969. ;
  1970. devcmd_online:
  1971.  ifnd    errordebonly
  1972.  bug     <"cnet: s2_online",10>
  1973.  endc
  1974.  
  1975.  move.l  a1,-(sp)
  1976.  move.l  io_device(a1),a0               ; a0 = device
  1977.  
  1978. ; This is a workaround for Genesis.. it calls
  1979. ; S2_ONLINE before S2_CONFIGINTERFACE.
  1980.  btst    #DDB_ONLINE,dd_flags+1(a0)     ; already online ?
  1981.  bne.s   .done
  1982.  
  1983.  btst    #DDB_CONFIGURED,dd_flags+1(a0) ; won't go online unless configured!
  1984.  beq.s   .unconfigured
  1985.  btst    #DDB_NICUP,dd_flags+1(a0)      ; nic initialised ?
  1986.  beq.s   .uninit
  1987.  
  1988.  bclr    #DDB_OFFLINE,dd_flags+1(a0)
  1989.  bset    #DDB_ONLINE,dd_flags+1(a0)     ; mark being online
  1990.  
  1991.  move.b  dd_rcr(a0),nic_rcr             ; set receiver to normal mode
  1992.  
  1993.  moveq   #S2EVENT_ONLINE,D0
  1994.  bsr     DoEvent                        ; return any ONLINE events
  1995.  
  1996. .done:
  1997.  move.l  (sp)+,a1
  1998.  bra     TermIO
  1999.  
  2000.  
  2001. .unconfigured:
  2002.  moveq   #S2WERR_NOT_CONFIGURED,d0       ; error, device is not configured
  2003.  move.b  #S2ERR_BAD_STATE,io_error(a1)   ; bug! was: (a2)
  2004.  bra.s   .error
  2005.  
  2006. .uninit:
  2007.  moveq   #S2WERR_UNIT_OFFLINE,d0
  2008.  move.b  #S2ERR_OUTOFSERVICE,io_error(a1)
  2009. .error:
  2010.  move.l  d0,ios2_wireerror(a1)
  2011.  bra.s   .done
  2012.  
  2013.  
  2014.  
  2015.  
  2016. ;==============================================
  2017. ;               S2_OFFLINE
  2018. ;==============================================
  2019. ;
  2020. ;           take device offline
  2021. ;
  2022. ;
  2023. devcmd_offline:
  2024.  ifnd    errordebonly
  2025.  bug     <"cnet: s2_offline",10>
  2026.  endc
  2027.  
  2028.  movem.l a1/a6,-(sp)
  2029.  move.l  io_device(a1),a0               ; a0 = device
  2030.  bset    #DDB_OFFLINE,dd_flags+1(a0)
  2031.  bclr    #DDB_ONLINE,dd_flags+1(a0)     ; test and clear - already offline ?
  2032.  beq.s   .done
  2033.  
  2034.  btst    #DDB_NICUP,dd_flags+1(a0)
  2035.  beq.s   .nicoff
  2036.  move.b  #DSRC_MON,nic_rcr              ; set receiver to monitor mode
  2037. .nicoff:
  2038.  
  2039.  move.l  exec_base(pc),a6
  2040.  ifnd    errordebonly
  2041.  bug     <"cnet: s2_offline **NOT** aborting read/readorphan/write requests!",10>
  2042.  endc
  2043.  ifgt    0
  2044.  SOFTDISABLE
  2045. ; a0=device
  2046.  moveq   #S2ERR_OUTOFSERVICE,d0
  2047.  moveq   #S2WERR_UNIT_OFFLINE,d1
  2048.  bsr     AbortRW
  2049.  SOFTENABLE
  2050.  endc
  2051.  
  2052.  moveq   #S2EVENT_OFFLINE,d0
  2053.  bsr     DoEvent                        ; return any OFFLINE events
  2054.  
  2055. .done:
  2056.  movem.l (sp)+,a1/a6
  2057.  bra     TermIO
  2058.  
  2059.  
  2060.  
  2061. ;==============================================
  2062. ;               S2_ONEVENT
  2063. ;==============================================
  2064. ;
  2065. ;         queue up event requests
  2066. ;
  2067. ;  online/offline return immediately if the conditon is met.
  2068. ;
  2069. devcmd_onevent:
  2070.  ifnd    errordebonly
  2071.  bug     <"cnet: s2_onevent mask $%08lx",10>,ios2_wireerror(a1)
  2072.  endc
  2073.  
  2074.  movem.l a3/a6,-(sp)
  2075.  move.l  io_device(a1),a3            ; a3 = device
  2076.  
  2077. ; do we know the requested events?
  2078.  move.l  ios2_wireerror(a1),d0
  2079.  and.l   #~(S2EVENT_ERROR|S2EVENT_TX|S2EVENT_RX|S2EVENT_ONLINE|S2EVENT_OFFLINE|S2EVENT_BUFF|S2EVENT_HARDWARE),d0
  2080.  bne     .unknown
  2081.  
  2082.  move.l  ios2_wireerror(a1),d0
  2083.  and.l   #S2EVENT_ONLINE,d0          ; waiting for online event ?
  2084.  beq.s   .noton
  2085.  btst    #DDB_ONLINE,dd_flags+1(a3)  ; currently online ?
  2086.  bne.s   .rtn
  2087.  bra.s   .queue
  2088.  
  2089. .noton:
  2090.  move.l  ios2_wireerror(a1),d0
  2091.  and.l   #S2EVENT_OFFLINE,d0         ; waiting for offline event ?
  2092.  beq.s   .queue
  2093.  btst    #DDB_ONLINE,dd_flags+1(a3)  ; currently offline ?
  2094.  bne.s   .queue
  2095.  
  2096. .rtn:
  2097.  ifnd    errordebonly
  2098.  bug     <"is (on|off)line",10>
  2099.  endc
  2100.  move.l  d0,ios2_wireerror(a1)       ; return immediately
  2101. ;already! clr.b   io_error(a1)
  2102. .term:
  2103.  bsr     TermIO
  2104.  bra.s   .done
  2105.  
  2106. .queue:
  2107.  ifnd    errordebonly
  2108.  bug     <"queued",10>
  2109.  endc
  2110.  bclr    #IOB_QUICK,io_flags(a1)     ; must be queued
  2111.  move.l  exec_base(pc),a6
  2112.  lea     dd_eventlist(a3),a0
  2113.  SOFTDISABLE
  2114.  ADDTAIL                             ; add ioreq to event queue
  2115.  SOFTENABLE
  2116.  
  2117. .done:
  2118.  movem.l (sp)+,a3/a6
  2119.  rts
  2120.  
  2121. .unknown:
  2122.  bug     <"cnet: s2_onevent mask $%08lx - unknown events requested!",10>,ios2_wireerror(a1)
  2123.  moveq   #S2WERR_BAD_EVENT,d0
  2124.  move.b  #S2ERR_NOT_SUPPORTED,io_error(a1)
  2125.  move.l  d0,ios2_wireerror(a1)
  2126.  bra.s   .term
  2127.  
  2128.  
  2129.  
  2130. ;==============================================
  2131. ;             S2_DEVICEQUERY
  2132. ;==============================================
  2133. ;
  2134. devcmd_devicequery:
  2135.  ifnd    errordebonly
  2136.  bug     <"cnet: s2_devicequery",10>
  2137.  endc
  2138.  
  2139.  move.l  a1,-(sp)
  2140.  move.l  ios2_statdata(a1),a0    ; a0 = caller's buffer
  2141.  move.l  (a0),d1                 ; d1 = buffer size
  2142.  move.l  size_supplied(pc),d0
  2143.  cmp.l   d0,d1                   ; enough space to store info?
  2144.  bhs.s   .get
  2145.  
  2146.  clr.l   S2DQ_SIZESUPPLIED(a0)   ; nope!
  2147. .bad:
  2148.  moveq   #S2WERR_BAD_STATDATA,d0
  2149.  move.b  #S2ERR_BAD_ARGUMENT,io_error(a1)
  2150.  move.l  d0,ios2_wireerror(a1)
  2151.  bra.s   .done
  2152.  
  2153. .get:
  2154.  lea     S2DQ_SIZESUPPLIED(a0),a1
  2155.  lea     size_supplied(pc),a0
  2156.  
  2157.  subq.l  #4,d0                   ; skip bytes_available
  2158.  bra.s   .copy
  2159. .copyloop:
  2160.  move.b  (a0)+,(a1)+             ; copy info to caller's buffer
  2161. .copy:
  2162.  subq.w  #1,d0
  2163.  bpl.s   .copyloop
  2164.  
  2165. .done:
  2166.  move.l  (sp)+,a1
  2167.  bra     TermIO
  2168.  
  2169.  
  2170.  
  2171. ;==============================================
  2172. ;           S2_GETSTATIONADDRESS
  2173. ;==============================================
  2174. ;
  2175. devcmd_getstationaddress:
  2176.  ifnd    errordebonly
  2177.  bug     <"cnet: s2_getstationaddress",10>
  2178.  endc
  2179.  
  2180.  move.l  io_device(a1),a0
  2181.  move.l  a1,-(sp)
  2182.  lea     dd_stationaddress(a0),a0
  2183.  lea     ios2_srcaddr(a1),a1     ; source address = station address
  2184.  bsr.s   .makeit
  2185.  lea     -ETHER_ADDR_SIZE*2(a0),a0   ; dest address = default address
  2186.  bsr.s   .makeit
  2187.  
  2188.  move.l  (sp)+,a1
  2189.  bra     TermIO
  2190.  
  2191. .makeit:
  2192.  move.l  (a0)+,(a1)+
  2193.  move.w  (a0)+,(a1)+
  2194.  clr.w   (a1)+
  2195.  clr.l   (a1)+
  2196.  clr.l   (a1)+
  2197.  rts
  2198.  
  2199.  
  2200.  
  2201. ;==============================================
  2202. ;             S2_CONFIGINTERFACE
  2203. ;==============================================
  2204. ;
  2205. ; NOTE: a default station address has already
  2206. ;       been set by init_nic
  2207. ;
  2208. devcmd_configinterface:
  2209.  ifnd    errordebonly
  2210.  bug     <"cnet: s2_configinterface",10>
  2211.  endc
  2212.  
  2213.  move.l  io_device(a1),a0
  2214.  bset    #DDB_CONFIGURED,dd_flags+1(a0) ; test and set - already configured ?
  2215.  bne     .already
  2216.  
  2217.  move.l  a6,-(sp)
  2218.  move.l  exec_base(pc),a6
  2219.  MYDISABLE
  2220.  
  2221.  move.l  ios2_srcaddr(a1),d0
  2222.  ble     .badaddr                       ; check for valid address
  2223.  
  2224.  lea     dd_stationaddress(a0),a0
  2225.  move.l  d0,(a0)
  2226.  move.w  ios2_srcaddr+4(a1),4(a0)
  2227.  
  2228.  move.b  nic_cr,d1                      ; remember current command
  2229.  delay
  2230.  move.b  #DSCM_NODMA|DSCM_PG1,nic_cr    ; select bank 1
  2231.  delay
  2232.  move.b  (a0)+,nic_par0
  2233.  delay
  2234.  move.b  (a0)+,nic_par1
  2235.  delay
  2236.  move.b  (a0)+,nic_par2
  2237.  delay                                  ; set station address
  2238.  move.b  (a0)+,nic_par3
  2239.  delay
  2240.  move.b  (a0)+,nic_par4
  2241.  delay
  2242.  move.b  (a0),nic_par5
  2243.  delay
  2244.  move.b  d1,nic_cr                      ; restore command
  2245.  
  2246. .done:
  2247.  MYENABLE
  2248.  move.l  (sp)+,a6
  2249. .termit:
  2250.  bra     TermIO
  2251.  
  2252. .badaddr:
  2253.  bclr    #DDB_CONFIGURED,dd_flags+1(a0) ; NOT configured!
  2254.  moveq   #S2WERR_SRC_ADDRESS,d0         ; error, source address bad
  2255.  move.b  #S2ERR_BAD_ADDRESS,io_error(a1)
  2256.  move.l  d0,ios2_wireerror(a1)
  2257.  bra.s   .done
  2258.  
  2259. .already
  2260.  moveq   #S2WERR_IS_CONFIGURED,d0       ; error, already configured
  2261.  move.b  #S2ERR_BAD_STATE,io_error(a1)
  2262.  move.l  d0,ios2_wireerror(a1)
  2263.  bra.s   .termit
  2264.  
  2265.  
  2266.  
  2267. ;==============================================
  2268. ;              S2_MULTICAST
  2269. ;==============================================
  2270. ;
  2271. devcmd_multicast:
  2272.  ifnd    errordebonly
  2273.  bug     <"cnet: s2_multicast %08lx%04x",10>,ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  2274.  endc
  2275.  
  2276.  btst    #0,ios2_dstaddr(a1)      ; is dest a multicast address ?
  2277.  bne     devcmd_write
  2278.  
  2279.  move.l  a1,-(sp)
  2280.  moveq   #S2EVENT_TX,d0           ; return any TX events
  2281.  bsr     DoEvent
  2282.  move.l  (sp)+,a1
  2283.  
  2284.  moveq   #S2WERR_BAD_MULTICAST,d0 ; wasn't a multicast addr
  2285.  move.b  #S2ERR_BAD_ADDRESS,io_error(a1)
  2286.  move.l  d0,ios2_wireerror(a1)
  2287.  bra     TermIO
  2288.  
  2289.  
  2290.  
  2291. ;==============================================
  2292. ;              S2_BROADCAST
  2293. ;==============================================
  2294. ;
  2295. devcmd_broadcast:
  2296.  ifnd    errordebonly
  2297.  bug     <"cnet: s2_broadcast",10>
  2298.  endc
  2299.  
  2300.  moveq   #-1,d0
  2301.  move.l  d0,ios2_dstaddr+0(a1)    ; dest address = BROADCAST (255)
  2302.  move.w  d0,ios2_dstaddr+4(a1)    ; dest address = BROADCAST (255)
  2303.  
  2304.  bra     devcmd_write
  2305.  
  2306.  
  2307.  
  2308. ;============================================
  2309. ;              S2_TRACKTYPE
  2310. ;============================================
  2311. ;
  2312. ; This function adds a packet type to the
  2313. ; list of those that are being tracked.
  2314. ;
  2315. devcmd_tracktype:
  2316.  ifnd    errordebonly
  2317.  bug     <"cnet: s2_tracktype %ld",10>,ios2_packettype(a1)
  2318.  endc
  2319.  
  2320.  movem.l a2-a4/a6,-(sp)
  2321.  move.l  exec_base(pc),a6
  2322.  move.l  a1,a2                         ; a2 = ioreq
  2323.  move.l  io_device(a1),a3
  2324.  
  2325.  moveq   #ss2_sizeof,d0                ; alloc tracking node
  2326.  bsr     alloc
  2327.  tst.l   d0
  2328.  bne.s   .gotmem
  2329.  
  2330.  ; error, can't allocate memory!
  2331.  moveq   #S2WERR_NOT_TRACKED,d0
  2332.  move.b  #S2ERR_NO_RESOURCES,io_error(a2)
  2333.  move.l  d0,ios2_wireerror(a2)
  2334.  bra.s   .done
  2335.  
  2336. .gotmem
  2337.  move.l  d0,a4
  2338.  
  2339.  move.l  ios2_packettype(a2),d0        ; d0 = our packet type
  2340.  
  2341.  SOFTDISABLE                           ; lock access to list
  2342.  move.l  dd_tracklist(a3),a0           ; a0 = 1st entry in list
  2343.  bra.s   .start
  2344.  
  2345. .search:
  2346.  cmp.l   ss2_ptype(a0),d0              ; = our packet type ?
  2347.  beq.s   .duperr
  2348.  move.l  d1,a0
  2349. .start:
  2350.  move.l  (a0),d1
  2351.  bne.s   .search                       ; end of list ?
  2352.  
  2353.  move.l  a4,a1
  2354.  move.l  ios2_packettype(a2),ss2_ptype(a1)  ; set tracking type
  2355.  lea     dd_tracklist(a3),a0
  2356.  ADDTAIL                                    ; add new tracktype node to list
  2357.  
  2358.  SOFTENABLE                            ; release lock on lists
  2359.  
  2360. .done:
  2361.  move.l  a2,a1
  2362.  movem.l (sp)+,a2-a4/a6
  2363.  bra     TermIO
  2364.  
  2365.  
  2366. .duperr:
  2367.  SOFTENABLE                            ; release lock on lists
  2368.  
  2369.  move.l  a4,a1
  2370.  moveq   #ss2_sizeof,d0                ; free tracking node
  2371.  bsr     free
  2372.  
  2373.  moveq   #S2WERR_ALREADY_TRACKED,d0
  2374.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2375.  move.l  d0,ios2_wireerror(a2)         ; error, type is tracked already!
  2376.  bra.s   .done
  2377.  
  2378.  
  2379.  
  2380. ;==============================================
  2381. ;             S2_UNTRACKTYPE
  2382. ;==============================================
  2383. ;
  2384. ; This function removes a packet type from the
  2385. ; list of those that are being tracked.
  2386. ;
  2387. devcmd_untracktype:
  2388.  ifnd    errordebonly
  2389.  bug     <"cnet: s2_untracktype %ld",10>,ios2_packettype(a1)
  2390.  endc
  2391.  
  2392.  movem.l a2-a3/a6,-(sp)
  2393.  move.l  exec_base(pc),a6
  2394.  move.l  a1,a2                  ; a2 = ioreq
  2395.  move.l  io_device(a1),a0
  2396.  move.l  ios2_packettype(a2),d0 ; d0 = packet type to untrack
  2397.  
  2398.  SOFTDISABLE                    ; lock access to list
  2399.  move.l  dd_tracklist(a0),a3    ; a3 = 1st entry in tracking list
  2400.  bra.s   .start
  2401.  
  2402. .search:
  2403.  cmp.l   ss2_ptype(a3),d0       ; found our packet type ?
  2404.  beq.s   .found
  2405.  move.l  d1,a3                  ; a3 = next entry
  2406. .start:
  2407.  move.l  (a3),d1
  2408.  bne.s   .search                ; end of list?
  2409.  
  2410.  ; could not find the type
  2411.  
  2412.  SOFTENABLE                     ; unlock access to list
  2413.  
  2414.  moveq   #S2WERR_NOT_TRACKED,d0        ; error, no tracktype!
  2415.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2416.  move.l  d0,ios2_wireerror(a2)
  2417.  bra.s   .done
  2418.  
  2419. .found:
  2420.  move.l  a3,a1
  2421.  REMOVE                         ; remove entry from list
  2422.  SOFTENABLE                     ; unlock access to list
  2423.  
  2424.  move.l  a3,a1
  2425.  moveq   #ss2_sizeof,d0         ; free entry's memory
  2426.  bsr     free
  2427.  
  2428. .done:
  2429.  move.l  a2,a1
  2430.  movem.l (sp)+,a2-a3/a6
  2431.  bra     TermIO
  2432.  
  2433.  
  2434. .error:
  2435.  
  2436.  
  2437.  
  2438. ;==================================================
  2439. ;               S2_GETTYPESTATS
  2440. ;==================================================
  2441. ; This function returns statistics for a specific
  2442. ; type of packet that is being tracked.
  2443. ;
  2444. devcmd_gettypestats:
  2445.  ifnd    errordebonly
  2446.  bug     <"cnet: s2_gettypestats",10>
  2447.  endc
  2448.  
  2449.  movem.l a2/a6,-(sp)
  2450.  move.l  exec_base(pc),a6
  2451.  move.l  a1,a2                       ; a2 = ioreq
  2452.  move.l  io_device(a1),a0
  2453.  move.l  ios2_packettype(a2),d0      ; d0 = packettype
  2454.  
  2455.  SOFTDISABLE                         ; lock access to list
  2456.  move.l  dd_tracklist(a0),a0         ; a0 = 1st entry in tracking list
  2457.  bra.s   .start
  2458.  
  2459. .loop:
  2460.  move.l  d1,a0                       ; a0  = next entry
  2461. .start:
  2462.  move.l  (a0),d1                     ; end of list ?
  2463.  beq.s   .notfound
  2464.  cmp.l   ss2_ptype(a0),d0            ; found our track type ?
  2465.  bne.s   .loop
  2466.  
  2467. ; note that both ss2_stats and ios2_statdata are quaranteed to be
  2468. ; word aligned.
  2469.  lea     ss2_stats(a0),a0
  2470.  move.l  ios2_statdata(a2),a1
  2471.  moveq   #s2pts_size/4,d0
  2472. .copystats
  2473.  move.l  (a0)+,(a1)+                 ; copy stats to ioreq
  2474.  subq.l  #1,d0
  2475.  bne.s   .copystats
  2476.  
  2477. .done:
  2478.  SOFTENABLE                          ; release lock on list
  2479.  move.l  a2,a1
  2480.  movem.l (sp)+,a2/a6
  2481.  bra     TermIO
  2482.  
  2483. .notfound:
  2484.  moveq   #S2WERR_NOT_TRACKED,d0
  2485.  move.b  #S2ERR_BAD_STATE,io_error(a2)
  2486.  move.l  d0,ios2_wireerror(a2)       ; error, couldn't find track type
  2487.  bra.s   .done
  2488.  
  2489.  
  2490.  
  2491. ;==============================================
  2492. ;            S2_GETSPECIALSTATS
  2493. ;==============================================
  2494. ;
  2495. devcmd_getspecialstats:
  2496.  ifnd    errordebonly
  2497.  bug     <"cnet: s2_getspecialstats",10>
  2498.  endc
  2499.  
  2500.  movem.l a1-a2,-(sp)
  2501.  move.l  io_device(a1),a2                    ; a2 = unit
  2502.  move.l  ios2_statdata(a1),a1
  2503.  clr.l   s2ssh_recordcountsupplied(a1)
  2504.  move.l  (a1)+,d0                            ; check s2ssh_recordcountmax
  2505.  beq.s   .done
  2506.  
  2507.  addq.l  #1,(a1)+                            ; s2ssh_recordcountsupplied++
  2508.  move.l  a1,a0
  2509.  move.l  #S2SS_ETHERNET_BADMULTICAST,(a0)+   ; set type      }
  2510.  move.l  dd_badmulticasts(a2),(a0)+          ; set statistic } bad multi
  2511.  move.l  #multiname,(a0)+                    ; set name      }
  2512.  subq.l  #1,d0
  2513.  beq.s   .done                               ; want more ?
  2514.  
  2515.  addq.l  #1,-(a1)                            ; s2ssh_recordcountsupplied++
  2516.  move.l  #S2SS_ETHERNET_RETRIES,(a0)+        ; set type      }
  2517.  move.l  dd_retries(a2),(a0)+                ; set statistic } retries
  2518.  move.l  #retryname,(a0)+                    ; set name      }
  2519.  
  2520. .done:
  2521.  movem.l (sp)+,a1-a2
  2522.  bra     TermIO
  2523.  
  2524.  
  2525.  
  2526. ;==============================================
  2527. ;           S2_GETGLOBALSTATS
  2528. ;==============================================
  2529. ;
  2530. devcmd_getglobalstats:
  2531.  ifnd    errordebonly
  2532.  bug     <"cnet: s2_getglobalstats",10>
  2533.  endc
  2534.  
  2535.  move.l  a1,-(sp)
  2536.  move.l  io_device(a1),a0
  2537.  
  2538. ; note that both dd_devicestats and ios2_statdata are quaranteed to be
  2539. ; word aligned.
  2540. ;
  2541.  lea     dd_devicestats(a0),a0
  2542.  move.l  ios2_statdata(a1),a1
  2543.  moveq   #s2ds_size/4,d0
  2544. .copy:
  2545.  move.l  (a0)+,(a1)+             ; get sana2devicestats
  2546.  subq.l  #1,d0
  2547.  bne.s   .copy
  2548.  
  2549.  move.l  (sp)+,a1
  2550.  bra     TermIO
  2551.  
  2552.  
  2553.  
  2554. ;==============================================
  2555. ;              S2_ADDMULTICASTADDRESS
  2556. ;==============================================
  2557. ;
  2558. devcmd_addmulticast:
  2559.  ifnd    errordebonly
  2560.  bug     <"cnet: s2_addmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
  2561.  endc
  2562.  
  2563.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower = upper !
  2564.  move.l  ios2_srcaddr(a1),-(sp)
  2565.  move.l  ios2_srcaddr+4(a1),-(sp)
  2566.  move.l  ios2_srcaddr(a1),-(sp)
  2567.  
  2568. addmcast:
  2569.  movem.l a2-a4/a6,-(sp)
  2570.  move.l  a6,a3                       ; a3 = device
  2571.  move.l  exec_base(pc),a6
  2572.  move.l  a1,a4                       ; a4 = ioreq
  2573.  
  2574.  bsr.s   addmcastrange
  2575.  
  2576.  move.l  a4,a1
  2577.  movem.l (sp)+,a2-a4/a6
  2578.  lea     4*4(sp),sp
  2579.  bra     TermIO
  2580.  
  2581.  
  2582.  
  2583. ;==============================================
  2584. ;              S2_ADDMULTICASTADDRESSES
  2585. ;==============================================
  2586. ;
  2587. devcmd_addmulticasts:
  2588.  ifnd    errordebonly
  2589.  bug     <"cnet: s2_addmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  2590.  endc
  2591.  
  2592.  move.l  ios2_dstaddr+4(a1),-(sp)    ; upper
  2593.  move.l  ios2_dstaddr(a1),-(sp)
  2594.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower
  2595.  move.l  ios2_srcaddr(a1),-(sp)
  2596.  bra.s   addmcast
  2597.  
  2598.  
  2599.  
  2600.  
  2601. AMCRO    EQU 4+(4*4)
  2602. addmcastrange:
  2603.  btst    #0,AMCRO+0+0(sp)            ; is src a multicast address ?
  2604.  beq     .badmcast
  2605.  btst    #0,AMCRO+8+0(sp)            ; is dst a multicast address ?
  2606.  beq     .badmcast
  2607.  
  2608.  lea     dd_multicastssema(a3),a0
  2609.  jsr     _LVOObtainSemaphore(a6)     ; lock access to list
  2610.  move.l  dd_multicasts(a3),a0        ; a0 = first entry in multicast list
  2611.  bra.s   .getmulti
  2612.  
  2613. .check:
  2614.  move.l  AMCRO+0+0(sp),d0
  2615.  cmp.l   mcastar_loweraddr(a0),d0
  2616.  bne.s   .next
  2617.  move.w  AMCRO+0+4(sp),d0
  2618.  cmp.w   mcastar_loweraddr+4(a0),d0
  2619.  bne.s   .next
  2620.  move.l  AMCRO+8+0(sp),d0            ; is our address in an existing entry ?
  2621.  cmp.l   mcastar_upperaddr(a0),d0
  2622.  bne.s   .next                       
  2623.  move.w  AMCRO+8+4(sp),d0
  2624.  cmp.w   mcastar_upperaddr+4(a0),d0
  2625.  bne.s   .next
  2626.  
  2627.  addq.l  #1,mcastar_count(a0)        ; added same address again
  2628.  ifnd    errordebonly
  2629.  ifd     debug
  2630.  move.l  mcastar_count(a0),d0
  2631.  bug     <"cnet: mcast node $%lx count=%ld",10>,a0,d0
  2632.  endc
  2633.  endc
  2634.  bra     .unlock
  2635.  
  2636. .next:
  2637.  move.l  d1,a0                       ; get next node in list
  2638. .getmulti:
  2639.  move.l  (a0),d1                     ; end of list ?
  2640.  bne.s   .check
  2641.  
  2642.  moveq   #mcastar_sizeof,d0
  2643.  bsr     alloc                       ; allocate memory for multicast entry
  2644.  tst.l   d0
  2645.  beq.s   .nomem
  2646.  
  2647.  move.l  d0,a1                                  ; a1 = new entry
  2648.  move.w  #1,mcastar_count+2(a1)                 ; count = 1
  2649.  move.l  AMCRO+0+0(sp),mcastar_loweraddr(a1)
  2650.  move.w  AMCRO+0+4(sp),mcastar_loweraddr+4(a1)
  2651.  move.l  AMCRO+8+0(sp),mcastar_upperaddr(a1)
  2652.  move.w  AMCRO+8+4(sp),mcastar_upperaddr+4(a1)
  2653.  ifnd    errordebonly
  2654.  bug     <"cnet: new mcast node at $%08lx",10>,a1
  2655.  endc
  2656.  lea     dd_multicasts(a3),a0
  2657.  ADDTAIL                                        ; add to list
  2658.  move.l  a3,a0
  2659.  bsr     update_multicasts                      ; update multicasts in nic
  2660.  
  2661. .unlock
  2662.  lea     dd_multicastssema(a3),a0
  2663.  jmp     _LVOReleaseSemaphore(a6)    ; release lock on list
  2664.  
  2665.  
  2666. .badmcast:
  2667.  moveq   #S2WERR_BAD_MULTICAST,d0
  2668.  move.b  #S2ERR_BAD_ADDRESS,io_error(a4)
  2669.  move.l  d0,ios2_wireerror(a4)       ; invalid multicast address
  2670.  rts
  2671.  
  2672.  
  2673. .nomem:
  2674.  moveq   #S2WERR_GENERIC_ERROR,d0
  2675.  move.b  #S2ERR_NO_RESOURCES,io_error(a4)
  2676.  move.l  d0,ios2_wireerror(a4)
  2677.  bra.s   .unlock
  2678.  
  2679.  
  2680.  
  2681. ;==============================================
  2682. ;              S2_DELMULTICASTADDRESS
  2683. ;==============================================
  2684. ;
  2685. devcmd_delmulticast:
  2686.  ifnd    errordebonly
  2687.  bug     <"cnet: s2_delmulticastaddress %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1)
  2688.  endc
  2689.  
  2690.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower = upper !
  2691.  move.l  ios2_srcaddr(a1),-(sp)
  2692.  move.l  ios2_srcaddr+4(a1),-(sp)
  2693.  move.l  ios2_srcaddr(a1),-(sp)
  2694.  
  2695. remmcast:
  2696.  movem.l a2-a4/a6,-(sp)
  2697.  move.l  a6,a3                       ; a3 = device
  2698.  move.l  exec_base(pc),a6
  2699.  move.l  a1,a4                       ; a4 = ioreq
  2700.  
  2701.  bsr.s   delmcastrange
  2702.  
  2703.  move.l  a4,a1
  2704.  movem.l (sp)+,a2-a4/a6
  2705.  lea     4*4(sp),sp
  2706.  bra     TermIO
  2707.  
  2708.  
  2709.  
  2710. ;==============================================
  2711. ;              S2_DELMULTICASTADDRESSES
  2712. ;==============================================
  2713. ;
  2714. devcmd_delmulticasts:
  2715.  ifnd    errordebonly
  2716.  bug     <"cnet: s2_delmulticastaddresses %08lx%04x - %08lx%04x",10>,ios2_srcaddr(a1),ios2_srcaddr+2(a1),ios2_dstaddr(a1),ios2_dstaddr+2(a1)
  2717.  endc
  2718.  
  2719.  move.l  ios2_dstaddr+4(a1),-(sp)    ; upper
  2720.  move.l  ios2_dstaddr(a1),-(sp)
  2721.  move.l  ios2_srcaddr+4(a1),-(sp)    ; lower
  2722.  move.l  ios2_srcaddr(a1),-(sp)
  2723.  bra.s   remmcast
  2724.  
  2725.  
  2726.  
  2727. DMCRO    EQU 4+(4*4)
  2728. delmcastrange:
  2729.  lea     dd_multicastssema(a3),a0
  2730.  jsr     _LVOObtainSemaphore(a6)     ; lock access to list
  2731.  move.l  dd_multicasts(a3),a2        ; a2 = first entry in multicast list
  2732.  bra.s   .getmulti
  2733.  
  2734. .check:
  2735.  move.l  DMCRO+0+0(sp),d0
  2736.  cmp.l   mcastar_loweraddr(a2),d0
  2737.  bne.s   .next
  2738.  move.w  DMCRO+0+4(sp),d0
  2739.  cmp.w   mcastar_loweraddr+4(a2),d0
  2740.  bne.s   .next
  2741.  move.l  DMCRO+8+0(sp),d0            ; is it our address ?
  2742.  cmp.l   mcastar_upperaddr(a2),d0
  2743.  bne.s   .next
  2744.  move.w  DMCRO+8+4(sp),d0
  2745.  cmp.w   mcastar_upperaddr+4(a2),d0
  2746.  bne.s   .next
  2747.  
  2748.  subq.l  #1,mcastar_count(a2)        ; one less count
  2749.  bne.s   .done
  2750.  
  2751.  ifnd    errordebonly
  2752.  bug     <"cnet: mcast entry $%08lx removed",10>,a2
  2753.  endc
  2754.  move.l  a2,a1
  2755.  REMOVE                              ; remove entry from list
  2756.  move.l  a2,a1
  2757.  moveq   #mcastar_sizeof,d0          ; free memory used by entry
  2758.  bsr     free
  2759.  
  2760.  move.l  a3,a0
  2761.  bsr     update_multicasts           ; update multicasts in nic
  2762.  bra.s   .done
  2763.  
  2764. .next:
  2765.  move.l  d1,a2                       ; get next node in list
  2766. .getmulti:
  2767.  move.l  (a2),d1                     ; end of list ?
  2768.  bne.s   .check
  2769.  
  2770.  moveq   #S2WERR_BAD_MULTICAST,d0
  2771.  move.b  #S2ERR_BAD_STATE,io_error(a4)
  2772.  move.l  d0,ios2_wireerror(a4)
  2773.  
  2774. .done:
  2775.  lea     dd_multicastssema(a3),a0
  2776.  jmp     _LVOReleaseSemaphore(a6)    ; release lock on list
  2777.  
  2778.  
  2779.  
  2780.  
  2781. ;================================================================
  2782. ;                    Update Multicasts
  2783. ;================================================================
  2784. ;
  2785. ;  calculate multicast hash table and send it to nic
  2786. ;
  2787. ;  as of 1.2beta4 multicasts can be a address range, also single
  2788. ;  addresses are defined with lower = upper.
  2789. ;
  2790. ;   update_multicasts(device)
  2791. ;                       a0
  2792. update_multicasts:
  2793.  movem.l d2-d4/a2-a3,-(sp)
  2794.  
  2795.  lea     prom_mcasthash(pc),a3   ; if promiscuous use hash bits of all 1's
  2796.  btst    #DDB_PROM,dd_flags+1(a0)
  2797.  bne.s   .isprom
  2798.  
  2799.  lea     dd_mcastaddr(a0),a3
  2800.  move.l  dd_multicasts(a0),a2
  2801.  clr.l   (a3)           ; clear all multicast bits
  2802.  clr.l   4(a3)
  2803.  
  2804.  subq.l  #8,sp          ; temp for address
  2805.  
  2806. .next:
  2807.  move.l  (a2),d4
  2808.  beq.s   .update        ; end of list ?
  2809.  move.l  mcastar_loweraddr(a2),(sp)
  2810.  move.w  mcastar_loweraddr+4(a2),4(sp)
  2811.  
  2812. .hashall:
  2813.  moveq   #-1,d0                 ; initial crc seed
  2814.  moveq   #6,d1                  ; 6 bytes in ethernet address
  2815.  move.l  sp,a0                  ; data to crc
  2816.  
  2817. .nextbyte:
  2818.  move.b  (a0)+,d3        ; get next data byte
  2819.  moveq   #8,d2           ; 8 bits in byte
  2820.  
  2821. .nextbit:
  2822.  lsl.l   #1,d0           ; crc << 1
  2823.  bcc.s   .crcnot1
  2824.  lsr.b   #1,d3           ; data >> 1
  2825.  bcc.s   .xor
  2826.  bra.s   .skipnext
  2827. .crcnot1:
  2828.  lsr.b   #1,d3           ; data >> 1
  2829.  bcc.s   .skipnext
  2830. .xor:
  2831.  eor.l   #$04c11db7,d0   ; crc = crc XOR polynomial
  2832. .skipnext:
  2833.  subq.l  #1,d2
  2834.  bne.s   .nextbit
  2835.  
  2836.  subq.l  #1,d1
  2837.  bne.s   .nextbyte
  2838.  
  2839.  rol.l   #6,d0
  2840.  and.w   #%0000000000111111,d0  ; isolate upper 6 bits
  2841.  move.w  d0,d1
  2842.  and.b   #%00000111,d0          ; d0 = bit in byte
  2843.  lsr.w   #3,d1                  ; d1 = byte offset
  2844.  bset    d0,0(a3,d1.w)          ; set bit for hashed multicast address
  2845.  
  2846.  
  2847.  move.l  mcastar_upperaddr+2(a2),d0
  2848.  move.w  mcastar_upperaddr(a2),d1
  2849.  cmp.l   2(sp),d0       ; all done with this range ?
  2850.  bne.s   .still
  2851.  cmp.w   (sp),d1
  2852.  beq.s   .donext        ; all done with this range ?
  2853. .still:
  2854. ; increment to next address...
  2855.  addq.l  #1,2(sp)
  2856.  bne.s   .hashall       ; did we overflow 32bit ?
  2857.  addq.w  #1,(sp)        ; 48bit add fix
  2858.  bra.s   .hashall
  2859.  
  2860. .donext:
  2861.  move.l  d4,a2
  2862.  bra.s   .next
  2863.  
  2864. .update:
  2865.  addq.l  #8,sp
  2866.  
  2867. .isprom
  2868.  bug     <"cnet: update_multicast: mask: $%08lx %08lx",10>,0(a3),4(a3)
  2869.  
  2870.  move.l  a3,a0
  2871.  bsr     put_multi      ; update multicast bits in nic
  2872.  
  2873.  movem.l (sp)+,d2-d4/a2-a3
  2874.  rts
  2875.  
  2876. ; "Promiscuous Physical." ... "In addition, the multicast hashing array must
  2877. ; be set to all 1's so that all multicast addresses are accepted."
  2878. prom_mcasthash:
  2879.  dc.l    $ffffffff,$ffffffff
  2880.  
  2881.  
  2882.  
  2883.  ifgt    0  ; this stuff inlined
  2884.  
  2885. ;==============================================================
  2886. ;                 hash multicast address
  2887. ;==============================================================
  2888. ; The nic does not compare multicast addresses directly, but
  2889. ; instead uses a bitfield of 64 bits - each bit corresponds
  2890. ; to a 6 bit hash code for the multicast address. If the bit
  2891. ; is set then any multicast address that matches the hash code
  2892. ; will be accepted.
  2893. ;
  2894. ; The hash code is generated by taking the upper 6 bits of the
  2895. ; 32 bit crc of the multicast address.
  2896. ;
  2897. ;  hash_multi(address)
  2898. ;               a0
  2899. ;
  2900. hash_multi:
  2901.  moveq   #-1,d0                 ; initial crc seed
  2902.  moveq   #6,d1                  ; 6 bytes in ethernet address
  2903.  
  2904.  bsr.s   calc_crc               ; calculate crc for this multicast address
  2905.  
  2906.  rol.l   #6,d0
  2907.  lea     mcastaddr(pc),a0
  2908.  and.w   #%0000000000111111,d0  ; isolate upper 6 bits
  2909.  move.w  d0,d1
  2910.  and.b   #%00000111,d0          ; d0 = bit in byte
  2911.  lsr.w   #3,d1                  ; d1 = byte offset
  2912.  bset    d0,0(a0,d1.w)          ; set bit for hashed multicast address
  2913.  rts
  2914.  
  2915.  
  2916.  
  2917. ;===========================================================================
  2918. ;                          Calculate 32 bit crc
  2919. ;===========================================================================
  2920. ;
  2921. ; - for each bit: if (crcbit=1 XOR databit=1) then crc=(crc XOR polynomial).
  2922. ; - polynomial is correct when data bits range 0-x, crc bits range 31-0.
  2923. ; - crc wraps at 32 bits.
  2924. ;
  2925. ;  crc = calc_crc(data, seed, bytelength)
  2926. ;   d0.l           a0    d0.l     d1.l
  2927. ;
  2928. calc_crc:
  2929.  movem.l d2/d3,-(sp)
  2930.  
  2931. .nextbyte:
  2932.  move.b  (a0)+,d3        ; get next data byte
  2933.  moveq   #8,d2           ; 8 bits in byte
  2934.  
  2935. .nextbit:
  2936.  lsl.l   #1,d0           ; crc << 1
  2937.  bcc.s   .crcnot1
  2938.  lsr.b   #1,d3           ; data >> 1
  2939.  bcc.s   .xor
  2940.  bra.s   .next
  2941. .crcnot1:
  2942.  lsr.b   #1,d3           ; data >> 1
  2943.  bcc.s   .next
  2944. .xor:
  2945.  eor.l   #$04c11db7,d0   ; crc = crc XOR polynomial
  2946. .next:
  2947.  subq.l  #1,d2
  2948.  bne.s   .nextbit
  2949.  
  2950.  subq.l  #1,d1
  2951.  bne.s   .nextbyte
  2952.  
  2953.  movem.l (sp)+,d2/d3
  2954.  rts
  2955.  
  2956.  endc
  2957.  
  2958.  
  2959.  
  2960. ;==============================================================
  2961. ;      Put Multicast address bitfield into NIC registers
  2962. ;==============================================================
  2963. ;
  2964. ;   put_multi(address)
  2965. ;               a0
  2966. ;
  2967. put_multi:
  2968.  move.l  a6,-(sp)
  2969.  move.l  exec_base(pc),a6
  2970.  MYDISABLE
  2971.  delay
  2972.  move.b  nic_cr,d0            ; save old command
  2973.  delay
  2974.  move.b  #DSCM_PG1|DSCM_NODMA|DSCM_STOP,nic_cr ; select page 1
  2975.  delay
  2976.  move.b  (a0)+,nic_mar0
  2977.  delay
  2978.  move.b  (a0)+,nic_mar1
  2979.  delay
  2980.  move.b  (a0)+,nic_mar2
  2981.  delay
  2982.  move.b  (a0)+,nic_mar3
  2983.  delay                        ; put Multicast bits
  2984.  move.b  (a0)+,nic_mar4
  2985.  delay
  2986.  move.b  (a0)+,nic_mar5
  2987.  delay
  2988.  move.b  (a0)+,nic_mar6
  2989.  delay
  2990.  move.b  (a0),nic_mar7
  2991.  delay
  2992.  move.b  d0,nic_cr            ; restore old command
  2993.  MYENABLE
  2994.  move.l  (sp)+,a6
  2995.  rts
  2996.  
  2997.  
  2998.  ifgt 0
  2999. ;=========================================================
  3000. ;              commands not supported
  3001. ;=========================================================
  3002. ;
  3003. devcmd_nosupport:
  3004.  bug     <"cnet: Unsupported command %d",10>,io_command-2(a1)
  3005.  
  3006.  moveq   #S2WERR_GENERIC_ERROR,d0
  3007.  move.b  #S2ERR_NOT_SUPPORTED,io_error(a1)
  3008.  move.l  d0,ios2_wireerror(a1)
  3009.  bra     TermIO
  3010.  
  3011.  endc
  3012.  
  3013.  
  3014. ;==========================================================
  3015. ;             doevent([device,] events)
  3016. ;                       a0       d0
  3017. ;==========================================================
  3018. ;
  3019. ; called when an 'important' event occurs
  3020. ;
  3021. DoEvent:
  3022.  ifnd    errordebonly
  3023.  bug     <"cnet: doevent $%08lx ...">,d0
  3024.  endc
  3025.  
  3026.  movem.l d2-d3/a2/a6,-(sp)
  3027.  move.l  exec_base(pc),a6
  3028.  move.l  d0,d2
  3029.  move.l  me_myself(pc),a0        ; get global pointer to self...
  3030.  SOFTDISABLE                     ; lock eventlist
  3031.  
  3032.  move.l  dd_eventlist(a0),a2     ; get first ioreq
  3033.  bra.s   .start
  3034.  
  3035. .loop:
  3036.  move.l  ios2_wireerror(a2),d0
  3037.  and.l   d2,d0                   ; ioreq for our events?
  3038.  beq.s   .next
  3039.  
  3040.  move.l  d0,ios2_wireerror(a2)   ; set the actual events
  3041.  move.l  a2,a1
  3042.  REMOVE                          ; remove ioreq from list
  3043.  move.b  #NT_REPLYMSG,ln_type(a2)
  3044.  move.l  a2,a1
  3045.  ifnd    errordebonly
  3046.  bug     <"cnet: returned eventreq $%lx",10>,a1
  3047.  endc
  3048.  jsr     _LVOReplyMsg(a6)        ; send reply to ioreq owner
  3049.  
  3050. .next:
  3051.  move.l  d3,a2                   ; next ioreq
  3052.  
  3053. .start:
  3054.  move.l  (a2),d3                 ; last ioreq ?
  3055.  bne.s   .loop
  3056.  
  3057.  SOFTENABLE                      ; unlock eventlist
  3058.  ifnd    errordebonly
  3059.  bug     <10,"cnet: doevent done",10>
  3060.  endc
  3061.  movem.l (sp)+,d2-d3/a2/a6
  3062.  rts
  3063.  
  3064.  
  3065.  
  3066. ;==================================================================
  3067. ;        RemoteRead(buffer, nicbuffer, length)
  3068. ;                     a1       d0.w     d1.w
  3069. ;==================================================================
  3070. ;
  3071. ; Get a copy of data stored in the network card's onboard RAM.
  3072. ;
  3073. ;  buffer     = Amiga RAM
  3074. ;
  3075. ;  nicbuffer  = 16 bit address in card memory
  3076. ;
  3077.  CNOP 0,4
  3078. ;RemoteRead:
  3079. REMOTEREAD MACRO
  3080.  
  3081.  ifd     turboio
  3082.  
  3083.  addq.w  #3,d1                   ; bump up count to even value
  3084.  and.w   #-4,d1
  3085.  ifndef  nocmdsave
  3086.  delay
  3087.  swap    d1
  3088.  move.b  nic_cr,d1               ; save old command
  3089.  swap    d1
  3090.  delay
  3091.  endc
  3092.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr ; select bank 0
  3093.  delay
  3094.  ifd     pedanticread
  3095.  move.b  #DSIS_RDC,nic_isr       ;   setup remote dma
  3096.  delay
  3097.  endc
  3098.  move.b  d1,nic_rbcr0            ;   set count.lo
  3099.  ror.w   #8,d1
  3100.  delay
  3101.  move.b  d1,nic_rbcr1            ;   set count.hi
  3102.  delay
  3103.  move.b  d0,nic_rsar0            ;   set address.lo
  3104.  ror.w   #8,d0
  3105.  delay
  3106.  move.b  d0,nic_rsar1            ;   set address.hi
  3107.  delay
  3108.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  3109.  ror.w   #8,d1
  3110.  move.w  d1,d0
  3111.  and.w   #%0000000000111100,d1
  3112.  lea     nic_data,a0
  3113.  lsr.w   #1,d1
  3114.  lsr.w   #6,d0
  3115.  neg.w   d1
  3116.  jmp     .rr_startread(pc,d1.w)
  3117. .rr_dmaread:
  3118.  move.l  (a0),(a1)+
  3119.  move.l  (a0),(a1)+
  3120.  move.l  (a0),(a1)+
  3121.  move.l  (a0),(a1)+
  3122.  move.l  (a0),(a1)+
  3123.  move.l  (a0),(a1)+
  3124.  move.l  (a0),(a1)+
  3125.  move.l  (a0),(a1)+
  3126.  move.l  (a0),(a1)+
  3127.  move.l  (a0),(a1)+
  3128.  move.l  (a0),(a1)+
  3129.  move.l  (a0),(a1)+
  3130.  move.l  (a0),(a1)+
  3131.  move.l  (a0),(a1)+
  3132.  move.l  (a0),(a1)+
  3133.  move.l  (a0),(a1)+
  3134. .rr_startread:
  3135.  subq.w  #1,d0
  3136.  bpl.s   .rr_dmaread
  3137.  
  3138.  ifd     pedanticread
  3139.  ; wait till done
  3140.  move.w  #DMATIMEOUT,d0          ; set timeout
  3141. .rd_check:
  3142.  delay
  3143.  btst    #DSIB_RDC,nic_isr       ; wait for remote DMA complete
  3144.  dbne    d0,.rd_check
  3145.  endc
  3146.  
  3147.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete (Ack intr.)
  3148.  ifndef  nocmdsave
  3149.  swap    d1
  3150.  delay
  3151.  move.b  d1,nic_cr               ; restore old command
  3152.  endc
  3153. ;rts
  3154.  
  3155.  else
  3156.  
  3157.  addq.w  #1,d1                   ; bump up count to even value
  3158.  and.w   #-2,d1
  3159.  ifndef  nocmdsave
  3160.  delay
  3161.  swap    d1
  3162.  move.b  nic_cr,d1               ; save old command
  3163.  swap    d1
  3164.  delay
  3165.  endc
  3166.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr ; select bank 0
  3167.  delay
  3168.  ifd     pedanticread
  3169.  move.b  #DSIS_RDC,nic_isr       ;   setup remote dma
  3170.  delay
  3171.  endc
  3172.  move.b  d1,nic_rbcr0            ;   set count.lo
  3173.  ror.w   #8,d1
  3174.  delay
  3175.  move.b  d1,nic_rbcr1            ;   set count.hi
  3176.  delay
  3177.  move.b  d0,nic_rsar0            ;   set address.lo
  3178.  ror.w   #8,d0
  3179.  delay
  3180.  move.b  d0,nic_rsar1            ;   set address.hi
  3181.  delay
  3182.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  3183.  ror.w   #8,d1
  3184.  move.w  d1,d0
  3185.  and.w   #%0000000000011110,d0
  3186.  lea     nic_data,a0
  3187.  neg.w   d0
  3188.  lsr.w   #5,d1
  3189.  jmp     .rr_startread(pc,d0.w)
  3190. .rr_dmaread:
  3191.  move.w  (a0),(a1)+
  3192.  move.w  (a0),(a1)+
  3193.  move.w  (a0),(a1)+
  3194.  move.w  (a0),(a1)+
  3195.  move.w  (a0),(a1)+
  3196.  move.w  (a0),(a1)+
  3197.  move.w  (a0),(a1)+
  3198.  move.w  (a0),(a1)+
  3199.  move.w  (a0),(a1)+
  3200.  move.w  (a0),(a1)+
  3201.  move.w  (a0),(a1)+
  3202.  move.w  (a0),(a1)+
  3203.  move.w  (a0),(a1)+
  3204.  move.w  (a0),(a1)+
  3205.  move.w  (a0),(a1)+
  3206.  move.w  (a0),(a1)+
  3207. .rr_startread:
  3208.  subq.w  #1,d1
  3209.  bpl.s   .rr_dmaread
  3210.  
  3211.  ifd     pedanticread
  3212.  ; wait till done
  3213.  move.w  #DMATIMEOUT,d0          ; set timeout
  3214. .rd_check:
  3215.  delay
  3216.  btst    #DSIB_RDC,nic_isr       ; wait for remote DMA complete
  3217.  dbne    d0,.rd_check
  3218.  endc
  3219.  
  3220.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete (Ack intr.)
  3221.  ifndef  nocmdsave
  3222.  swap    d1
  3223.  delay
  3224.  move.b  d1,nic_cr               ; restore old command
  3225.  endc
  3226. ;rts
  3227.  
  3228.  endc
  3229.  ENDM
  3230.  
  3231.  
  3232.  ; experimental - NE8390 RW BUGFIX
  3233.  ifgt 0
  3234.  
  3235. NE8390_RW_BUGFIX MACRO
  3236.  move.b  #$42,nic_rbcr0             ; set count.lo
  3237.  delay
  3238.  move.b  #$00,nic_rbcr1             ; set count.hi
  3239.  delay
  3240.  move.b  #$42,nic_rsar0             ; set address.lo
  3241.  delay
  3242.  move.b  #$00,nic_rsar1             ; set address.hi
  3243.  delay
  3244.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  3245.  delay
  3246.  ; make certain that the dummy read has occured.
  3247.  ;swap     d0
  3248.  ;move.w   #1500*6,d0
  3249. ;.dloop:
  3250.  ;tst.b    $bfe001       ; wait 6*1uS
  3251.  ;dbf      d0,.dloop
  3252.  ;swap     d0
  3253.  lea      $bfe001,a0
  3254.  tst.b    (a0)
  3255.  tst.b    (a0)
  3256.  ENDM
  3257.  
  3258.  else
  3259.  
  3260. NE8390_RW_BUGFIX MACRO
  3261.  ; do nothing
  3262.  ENDM
  3263.  
  3264.  endc
  3265.  
  3266. ;=================================================================
  3267. ;         RemoteWrite( buffer, nicbuffer, count )
  3268. ;                        a1      d0.w     d1.w
  3269. ;=================================================================
  3270. ;
  3271. ;      Puts data into the network card's onboard RAM
  3272. ;
  3273. ;  buffer    = Amiga memory
  3274. ;
  3275. ;  nicbuffer = 16 bit address in card RAM
  3276. ;
  3277. ;
  3278.  CNOP 0,4
  3279. ;RemoteWrite:
  3280. REMOTEWRITE MACRO
  3281.  ifd     turboio
  3282.  
  3283.  addq.w  #3,d1
  3284.  and.w   #-4,d1                     ; bump up count to even value
  3285.  ifndef  nocmdsave
  3286.  swap    d1
  3287.  delay
  3288.  move.b  nic_cr,d1                  ; save old command
  3289.  swap    d1
  3290.  delay
  3291.  endc
  3292.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr ; select bank 0
  3293.  delay
  3294.  
  3295.  NE8390_RW_BUGFIX
  3296.  
  3297.  move.b  #DSIS_RDC,nic_isr          ; remote DMA complete (Ack intr.)
  3298.  delay
  3299.  
  3300.  ; the normal output
  3301.  move.b  d1,nic_rbcr0               ; set count.lo
  3302.  ror.w   #8,d1
  3303.  delay
  3304.  move.b  d1,nic_rbcr1               ; set count.hi
  3305.  delay
  3306.  move.b  d0,nic_rsar0               ; set address.lo
  3307.  lsr.w   #8,d0
  3308.  delay
  3309.  move.b  d0,nic_rsar1               ; set address.hi
  3310.  delay
  3311.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
  3312.  ror.w   #8,d1
  3313.  
  3314. ; write the etherpacket header & prepare for the copy loop.
  3315.  lea     nic_data,a0
  3316.  sub.w   #ether_data+2,d1
  3317.  move.l  txbuffer(pc),(a0)
  3318.  move.w  d1,d0
  3319.  move.l  txbuffer+4(pc),(a0)
  3320.  and.w   #%0000000000111100,d1
  3321.  move.l  txbuffer+8(pc),(a0)
  3322.  lsr.w   #1,d1
  3323.  move.w  txbuffer+12(pc),(a0)
  3324.  lsr.w   #6,d0
  3325.  neg.w   d1
  3326.  move.w  (a1)+,(a0)
  3327.  jmp     .rw_startwrite(pc,d1.w)
  3328. .rw_dmawrite:
  3329.  move.l  (a1)+,(a0)
  3330.  move.l  (a1)+,(a0)
  3331.  move.l  (a1)+,(a0)
  3332.  move.l  (a1)+,(a0)
  3333.  move.l  (a1)+,(a0)
  3334.  move.l  (a1)+,(a0)
  3335.  move.l  (a1)+,(a0)
  3336.  move.l  (a1)+,(a0)
  3337.  move.l  (a1)+,(a0)
  3338.  move.l  (a1)+,(a0)
  3339.  move.l  (a1)+,(a0)
  3340.  move.l  (a1)+,(a0)
  3341.  move.l  (a1)+,(a0)
  3342.  move.l  (a1)+,(a0)
  3343.  move.l  (a1)+,(a0)
  3344.  move.l  (a1)+,(a0)
  3345. .rw_startwrite:
  3346.  subq.w  #1,d0
  3347.  bpl.s   .rw_dmawrite
  3348.  
  3349.  move.w  #DMATIMEOUT,d0             ; set timeout
  3350. .rw_check:
  3351.  delay
  3352.  btst    #DSIB_RDC,nic_isr          ; wait for remote DMA complete
  3353.  dbne    d0,.rw_check
  3354.  
  3355. ; d0.w = -1   send timed out
  3356. ; d0.w != -1  send succeeded
  3357.  
  3358.  delay
  3359.  move.b  #DSIS_RDC,nic_isr          ; Remote DMA complete (Ack intr.)
  3360.  ifndef  nocmdsave
  3361.  swap    d1
  3362.  delay
  3363.  move.b  d1,nic_cr                  ; restore old command
  3364.  endc
  3365. ;rts
  3366.  
  3367.  else
  3368.  
  3369.  addq.w  #1,d1
  3370.  and.w   #-2,d1                     ; bump up count to even value
  3371.  ifndef  nocmdsave
  3372.  swap    d1
  3373.  delay
  3374.  move.b  nic_cr,d1                  ; save old command
  3375.  swap    d1
  3376.  delay
  3377.  endc
  3378.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr ; select bank 0
  3379.  delay
  3380.  
  3381.  NE8390_RW_BUGFIX
  3382.  
  3383.  move.b  #DSIS_RDC,nic_isr          ; remote DMA complete (Ack intr.)
  3384.  delay
  3385.  
  3386.  ; the normal output
  3387.  move.b  d1,nic_rbcr0               ; set count.lo
  3388.  ror.w   #8,d1
  3389.  delay
  3390.  move.b  d1,nic_rbcr1               ; set count.hi
  3391.  delay
  3392.  move.b  d0,nic_rsar0               ; set address.lo
  3393.  lsr.w   #8,d0
  3394.  delay
  3395.  move.b  d0,nic_rsar1               ; set address.hi
  3396.  delay
  3397.  move.b  #DSCM_START|DSCM_RWRITE,nic_cr ; request remote write
  3398.  
  3399. ; write the etherpacket header & prepare for the copy loop.
  3400.  lea     nic_data,a0
  3401.  ror.w   #8,d1
  3402.  move.w  txbuffer(pc),(a0)
  3403.  sub.w   #ether_data,d1
  3404.  move.w  txbuffer+2(pc),(a0)
  3405.  move.w  d1,d0
  3406.  move.w  txbuffer+4(pc),(a0)
  3407.  move.w  txbuffer+6(pc),(a0)
  3408.  and.w   #%0000000000011110,d1
  3409.  move.w  txbuffer+8(pc),(a0)
  3410.  lsr.w   #5,d0
  3411.  move.w  txbuffer+10(pc),(a0)
  3412.  neg.w   d1
  3413.  move.w  txbuffer+12(pc),(a0)
  3414.  jmp     .rw_startwrite(pc,d1.w)
  3415. .rw_dmawrite:
  3416.  move.w  (a1)+,(a0)
  3417.  move.w  (a1)+,(a0)
  3418.  move.w  (a1)+,(a0)
  3419.  move.w  (a1)+,(a0)
  3420.  move.w  (a1)+,(a0)
  3421.  move.w  (a1)+,(a0)
  3422.  move.w  (a1)+,(a0)
  3423.  move.w  (a1)+,(a0)
  3424.  move.w  (a1)+,(a0)
  3425.  move.w  (a1)+,(a0)
  3426.  move.w  (a1)+,(a0)
  3427.  move.w  (a1)+,(a0)
  3428.  move.w  (a1)+,(a0)
  3429.  move.w  (a1)+,(a0)
  3430.  move.w  (a1)+,(a0)
  3431.  move.w  (a1)+,(a0)
  3432. .rw_startwrite:
  3433.  subq.w  #1,d0
  3434.  bpl.s   .rw_dmawrite
  3435.  
  3436.  move.w  #DMATIMEOUT,d0             ; set timeout
  3437. .rw_check:
  3438.  delay
  3439.  btst    #DSIB_RDC,nic_isr          ; wait for remote DMA complete
  3440.  dbne    d0,.rw_check
  3441.  
  3442. ; if d0.w<0 timed out
  3443. ; if d0.w>=0 succeeded
  3444.  
  3445.  delay
  3446.  move.b  #DSIS_RDC,nic_isr          ; Remote DMA complete (Ack intr.)
  3447.  ifndef  nocmdsave
  3448.  swap    d1
  3449.  delay
  3450.  move.b  d1,nic_cr                  ; restore old command
  3451.  endc
  3452. ;rts
  3453.  
  3454.  endc
  3455.  ENDM
  3456.  
  3457.  
  3458.  
  3459. ;=========================================================
  3460. ;                      reset_nic()
  3461. ;=========================================================
  3462. ;
  3463. ; NOTE: must preserve a0
  3464. ;
  3465. reset_nic:
  3466.  delay
  3467.  move.b  nic_rst,d0                       ; start reset pulse
  3468.  delay
  3469.  move.b  d0,nic_rst                       ; end reset pulse
  3470.  delay
  3471.  move.b  #DSCM_NODMA|DSCM_STOP,nic_cr     ; stop controller
  3472. ;
  3473. ; wait 1.5mS
  3474. ;
  3475.  move.w   #1500,d0
  3476. .loop:
  3477.  tst.b    $bfe001       ; wait 1uS
  3478.  dbf      d0,.loop
  3479.  
  3480.  move.b  #$ff,nic_isr                     ; clear all nic ints
  3481.  rts
  3482.  
  3483.  
  3484.  ifgt    0  ; this stuff inlined
  3485.  
  3486. ;======================
  3487. ;  delay approx 1.5mS
  3488. ;======================
  3489. ;
  3490. delay1500:
  3491.  move.l   d0,-(sp)
  3492.  move.w   #1500,d0
  3493. .loop:
  3494.  tst.b    $bfe001       ; wait 1uS
  3495.  dbf      d0,.loop
  3496.  move.l   (sp)+,d0
  3497.  rts
  3498.  
  3499.  endc
  3500.  
  3501.  
  3502. ;========================================================================
  3503. ;                           init_nic(flags, device)
  3504. ;                                     d0.l    a1
  3505. ;========================================================================
  3506. ;
  3507. ; Set up the network card for online operation. We also get the hardware
  3508. ; station address from the nic's ROM.
  3509. ;
  3510. ; flags:
  3511. ;   bit 0: if set don't display easyreq
  3512. ;
  3513. init_nic:
  3514.  movem.l d2/a5/a6,-(sp)
  3515.  move.l  d0,d2
  3516.  move.l  exec_base(pc),a6
  3517.  move.l  a1,a5                             ; a5 = device data
  3518.  MYDISABLE                                 ; ignore ints while setting up
  3519.  btst    #DDB_NICUP,dd_flags+1(a5)
  3520.  bne     .ok                               ; already initialised ?
  3521.  
  3522.  move.b  #DSDC_WTS|DSDC_FT1|DSDC_BMS,dd_dcr(a5)  ; Word Xfer, FIFO at 8 bytes, Burst
  3523.  
  3524.  move.b  #DSRC_AB|DSRC_AM,dd_rcr(a5)       ; accept broadcast & multicast
  3525.  btst    #DDB_PROM,dd_flags+1(a5)
  3526.  beq.s   .notprom                              ; if promiscuous..
  3527.  or.b    #DSRC_SEP|DSRC_PRO|DSRC_AR,dd_rcr(a5) ; ..accept all packets
  3528. .notprom:
  3529.  
  3530.  move.b  #INTMASK,dd_imr(a5)               ; accept useful interrupts
  3531.  bsr     reset_nic                         ; reset the controller
  3532.  delay
  3533.  move.b  nic_cr,d0                         ; get command
  3534.  cmp.b   #DSCM_NODMA|DSCM_STOP,d0
  3535.  lea     .error1(pc),a0
  3536.  bne     .error                            ; correct response ?
  3537.  
  3538.  delay
  3539.  move.b  dd_dcr(a5),nic_dcr                ; set data configuration register
  3540.  delay
  3541.  move.b  #0,nic_rbcr0                      ; clear remote byte count
  3542.  delay
  3543.  move.b  #0,nic_rbcr1                      ;         ''
  3544.  delay
  3545.  move.b  #DSRC_MON,nic_rcr                 ; set rx to monitor mode
  3546.  delay
  3547.  move.b  #DSTC_LB0,nic_tcr                 ; set tx to loopback mode 1
  3548.  delay
  3549.  move.b  #(RBUFEND/256)-1,nic_bnry         ; set boundary page
  3550.  delay
  3551.  move.b  #RBUF/256,nic_pstart              ; set start of rx ring buffer
  3552.  delay
  3553.  move.b  #RBUFEND/256,nic_pstop            ; set end of rx ring buffer
  3554.  delay
  3555.  move.b  #$ff,nic_isr                      ; clear all interrupts
  3556.  delay
  3557.  move.b  #0,nic_imr                        ; no interrupts allowed
  3558.  delay
  3559.  move.b  nic_rsr,d0
  3560.  delay
  3561.  move.b  nic_ncr,d0
  3562.  delay
  3563.  move.b  nic_cntr0,d0                      ; read status registers
  3564.  delay
  3565.  move.b  nic_cntr1,d0
  3566.  delay
  3567.  move.b  nic_cntr2,d0
  3568.  delay
  3569.  move.b  #ETHER_ADDR_SIZE*2,nic_rbcr0      ; byte count low = (words)
  3570.  delay
  3571.  move.b  #0,nic_rbcr1                      ; byte count high = 0
  3572.  delay
  3573.  move.b  #0,nic_rsar0                      ; remote start addr low = 0 (ROM)
  3574.  delay
  3575.  move.b  #0,nic_rsar1                      ; remote start addr high = 0 (ROM)
  3576.  delay
  3577.  move.b  #DSCM_RREAD,nic_cr                ; start remote read to get
  3578.  delay                                     ; station address from ROM
  3579.  lea     dd_romstationaddress(a5),a0
  3580.  
  3581.  moveq   #ETHER_ADDR_SIZE,d0
  3582. .getaddr:
  3583.  move.b  nic_data,(a0)+                    ; get ROM station address
  3584.  subq.l  #1,d0                             ; NOTE: 'move.b' as ROM is 8 bit
  3585.  bne.s   .getaddr                          
  3586.  
  3587. ;lea     dd_romstationaddress(a5),a0
  3588. ;bug     <"cnet: romstationaddress: %08lx%04lx",10>,(a0),2(a0)
  3589.  
  3590.  move.w  #DMATIMEOUT,d1
  3591. .waitloop:
  3592.  delay
  3593.  btst    #DSIB_RDC,nic_isr                 ; wait for remote DMA complete
  3594.  dbne    d1,.waitloop
  3595.  
  3596.  addq.w  #1,d1
  3597.  lea     .error2(pc),a0
  3598.  beq     .error_reset                      ; error if timed out
  3599.  delay
  3600.  move.b  #DSIS_RDC,nic_isr                 ; clear remote DMA complete int
  3601.  
  3602.  lea     dd_romstationaddress(a5),a0
  3603.  tst.b   (a0)
  3604.  bmi.s   .badaddr                          ; good station address ?
  3605.  
  3606.  move.l  2(a0),d0
  3607.  beq.s   .badaddr
  3608.  addq.l  #1,d0                             ; -1 ?
  3609.  bne.s   .gotstation
  3610. .badaddr:
  3611.  bug     <"cnet: init_nic: bad station address %08lx%04lx, using default",10>,(a0),2(a0)
  3612.  lea     default_address(pc),a0
  3613. .gotstation:
  3614.  ifnd    errordebonly
  3615.  bug     <"cnet: init_nic: station address set to %08lx%04lx",10>,(a0),2(a0)
  3616.  endc
  3617.  
  3618.  lea     dd_stationaddress(a5),a1
  3619.  move.l  (a0)+,(a1)+                       ; copy address to device data
  3620.  move.w  (a0)+,(a1)+
  3621.  
  3622.  lea     dd_stationaddress(a5),a0
  3623.  delay
  3624.  ifdef   nocmdsave
  3625.  MYDISABLE
  3626.  endc
  3627.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_STOP,nic_cr ; select bank 1
  3628.  delay
  3629.  move.b  (a0)+,nic_par0
  3630.  delay
  3631.  move.b  (a0)+,nic_par1
  3632.  delay
  3633.  move.b  (a0)+,nic_par2
  3634.  delay                                     ; set station address
  3635.  move.b  (a0)+,nic_par3
  3636.  delay
  3637.  move.b  (a0)+,nic_par4
  3638.  delay
  3639.  move.b  (a0),nic_par5
  3640.  delay
  3641.  move.b  #RBUF/256,nic_curr                ; set current page for rx
  3642.  moveq   #DSCM_NODMA|DSCM_START,d0         ; (also select bank 0)
  3643.  delay
  3644.  move.b  d0,nic_cr                         ; start controller
  3645.  ifdef   nocmdsave
  3646.  MYENABLE
  3647.  endc
  3648.  delay
  3649.  cmp.b   nic_cr,d0
  3650.  lea     .error3(pc),a0
  3651.  bne     .error_reset                      ; command accepted ?
  3652.  
  3653. ;;lea     dd_mcastaddr(a5),a0               ; initially all zero
  3654. ;;bsr     put_multi                         ; load multicast registers
  3655.  move.l  a5,a0
  3656.  bsr     update_multicasts                  ; load multicast registers
  3657.  
  3658.  delay
  3659.  move.b  dd_rcr(a5),nic_rcr                ; normal rx mode
  3660.  delay
  3661.  move.b  #DEF_TCR,nic_tcr                  ; loopback mode off
  3662.  delay
  3663.  move.b  #TBUF/256,nic_tpsr                ; init tx start page
  3664.  delay
  3665.  move.b  #$ff,nic_isr                      ; clear all interrupts
  3666.  delay
  3667.  move.b  dd_imr(a5),nic_imr                ; enable nic interrupts
  3668.  
  3669.  bset    #DDB_NICUP,dd_flags+1(a5)         ; nic is initialised
  3670.  
  3671. .ok:
  3672.  MYENABLE                                  ; allow interrupt processing
  3673.  
  3674.  move.l  a6,-(sp)
  3675.  move.l  dd_timereq+io_device(a5),a6
  3676.  lea     dd_devicestats+s2ds_laststart(a5),a0
  3677.  jsr     _LVOGetSysTime(a6)                ; record start time_of_day
  3678.  move.l  (sp)+,a6
  3679.  
  3680.  ifnd    errordebonly
  3681.  bug     <"cnet: init_nic Ok",10>
  3682.  endc
  3683.  moveq   #0,d0                             ; return OK
  3684.  
  3685. .pop:
  3686.  movem.l (sp)+,d2/a5/a6
  3687.  rts
  3688.  
  3689.  
  3690. .error1:
  3691.  bug     <"cnet: init_nic: failed reset, card not compatible?",10>
  3692.  lea     .errmsg1(pc),a0
  3693.  bra     EasyReq
  3694.  
  3695. .error2:
  3696.  bug     <"cnet: init_nic: DMA timeout getting station address!",10>
  3697.  lea     .errmsg2(pc),a0
  3698.  bra     EasyReq
  3699.  
  3700. .error3:
  3701.  bug     <"cnet: init_nic: failed to start controller, card faulty?",10>
  3702.  lea     .errmsg3(pc),a0
  3703.  bra     EasyReq
  3704.  
  3705. .error_reset:
  3706.  bsr     reset_nic                         ; reset nic after malfunction
  3707. .error:
  3708.  move.l  a0,a5
  3709.  moveq   #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
  3710.  bsr     DoEvent
  3711.  MYENABLE
  3712.  btst    #0,d2
  3713.  bne.b   .noreq
  3714.  jsr     (a5)
  3715. .noreq:
  3716.  moveq   #-1,d0                            ; return error
  3717.  bra     .pop
  3718.  
  3719.  
  3720. .errmsg1
  3721.  dc.b    "card reset failed,",10,"card not compatible?",0
  3722.  
  3723. .errmsg2
  3724.  dc.b    "DMA timeout getting",10,"hardware station address",0
  3725.  
  3726. .errmsg3
  3727.  dc.b    "failed to start controller,",10,"card not compatible?",0
  3728.  CNOP    0,2
  3729.  
  3730.  
  3731. ;--------------------------------------------------------
  3732. ;                     easyreq(bodymsg, args)
  3733. ;                               a0      a1
  3734. ;--------------------------------------------------------
  3735. ;
  3736. easyreq:
  3737.  movem.l a2-a4/a6,-(sp)
  3738.  move.l  a0,a2
  3739.  move.l  a1,a3
  3740.  move.l  exec_base(pc),a6
  3741.  
  3742.  move.l  #4096+16,d0
  3743.  moveq   #MEMF_PUBLIC,d1
  3744.  jsr     _LVOAllocVec(a6)
  3745.  tst.l   d0
  3746.  beq.s   .exit
  3747.  move.l  d0,a4
  3748.  add.l   #16,d0
  3749.  move.l  d0,(a4)             ; stk_Lower
  3750.  add.l   #4096,d0
  3751.  move.l  d0,4(a4)            ; stk_Upper
  3752.  move.l  d0,8(a4)            ; stk_Pointer
  3753.  move.l  a4,a0
  3754.  jsr     _LVOStackSwap(a6)
  3755.  
  3756.  lea     .intuiname(pc),a1
  3757.  moveq   #36,d0
  3758.  jsr     _LVOOpenLibrary(a6)
  3759.  tst.l   d0
  3760.  beq.s   .nointui
  3761.  move.l  d0,a6
  3762.  
  3763.  pea     .gadgets(pc)        ; es_GadgetFormat
  3764.  move.l  a2,-(sp)            ; es_TextFormat
  3765.  pea     IDString(pc)        ; es_Title
  3766.  clr.l   -(sp)               ; es_Flags
  3767.  pea     (4*5).w             ; es_StructSize
  3768.  
  3769.  sub.l   a0,a0
  3770.  move.l  sp,a1
  3771.  sub.l   a2,a2
  3772.  ; a3 = arglist
  3773.  jsr     _LVOEasyRequestArgs(a6)
  3774.  lea     (5*4,sp),sp
  3775.  move.l  d0,a2
  3776.  
  3777.  move.l  a6,a1
  3778.  move.l  exec_base(pc),a6
  3779.  jsr     _LVOCloseLibrary(a6)
  3780.  
  3781. .nointui
  3782.  move.l  a4,a0
  3783.  jsr     _LVOStackSwap(a6)
  3784.  move.l  a4,a1
  3785.  jsr     _LVOFreeVec(a6)
  3786.  
  3787. .exit:
  3788.  movem.l (sp)+,a2-a4/a6
  3789.  rts
  3790.  
  3791. .intuiname:
  3792.  dc.b    "intuition.library",0
  3793. .gadgets:
  3794.  dc.b    "Ok",0
  3795.  CNOP    0,2
  3796.  
  3797.  
  3798. ;--------------------------------------------------------
  3799. ;                     kill_nic(device)
  3800. ;                                a1
  3801. ;--------------------------------------------------------
  3802. ;
  3803. kill_nic:
  3804.  ifnd    errordebonly
  3805.  bug     <"cnet: kill_nic",10>
  3806.  endc
  3807.  
  3808.  move.l  a6,-(sp)
  3809.  move.l  exec_base(pc),a6
  3810.  MYDISABLE
  3811.  
  3812.  bclr    #DDB_NICUP,dd_flags+1(a1) ; test and clear - nic up ?
  3813.  beq.s   .done                    ; already killed ?
  3814.  bsr     reset_nic                ; reset controller
  3815.  delay
  3816.  move.b  #DSRC_MON,nic_rcr        ; set rx to monitor mode
  3817.  delay
  3818.  move.b  #DSTC_LB0,nic_tcr        ; set tx to loopback mode
  3819. .done:
  3820.  
  3821.  MYENABLE
  3822.  move.l  (sp)+,a6
  3823.  rts
  3824.  
  3825.  
  3826.  
  3827. ;========================================================
  3828. ;                 txintcode(device)
  3829. ;                             a1
  3830. ;========================================================
  3831. ;
  3832. ;  send packets to network card. packets will be put
  3833. ;  into the card's onboard 16 bit ram, and then
  3834. ;  transmitted to the wire.
  3835. ;
  3836. ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
  3837. ;
  3838. txintcode:
  3839. ;bug     <"cnet: *** tx int",10>
  3840.  
  3841.  movem.l d2-d4/a2-a3/a6,-(sp)
  3842.  move.l  exec_base(pc),a6
  3843.  move.l  a1,a5                      ; a5 = device
  3844.  
  3845. .next:
  3846.  btst    #DDB_TX,dd_flags+1(a5)     ; quit if tx in progress (status int
  3847.  bne.s   .done                      ; will restart us when tx complete)
  3848.  
  3849.  lea     dd_writelist(a5),a0
  3850.  MYREMHEAD                          ; remove top ioreq
  3851.  bne.s   .gotreq                    ; any ioreqs to process?
  3852.  
  3853. .done:
  3854.  movem.l (sp)+,d2-d4/a2-a3/a6
  3855. ;; moveq   #0,d0
  3856.  rts
  3857.  
  3858.  
  3859. .gotreq:
  3860.  move.l  d0,a3                      ; a3 = ioreq
  3861.  
  3862.  lea     txbuffer(pc),a1            ; a1 = our internal packet buffer
  3863.  move.l  ios2_buffermanagement(a3),a2
  3864.  move.l  ios2_datalength(a3),d4     ; default: raw packet's full length
  3865.  move.l  ios2_packettype(a3),d3     ; d3 = packettype (must be in d3 in non-raw too!!!)
  3866.  tst.b   io_flags(a3)               ; (test SANA2IOB_RAW) raw packets?
  3867.  bmi.s   .send
  3868.  
  3869. ; ok. it's not raw packet so we need to build etherheader for it.
  3870. ; first destination and source addresses then packet type. easy!
  3871.  
  3872.  lea     ios2_dstaddr(a3),a0        ; dstaddress
  3873.  move.l  (a0)+,(a1)+
  3874.  move.w  (a0)+,(a1)+
  3875.  lea     dd_stationaddress(a5),a0   ; from address
  3876.  move.l  (a0)+,(a1)+
  3877.  move.w  (a0)+,(a1)+
  3878.  move.w  d3,(a1)+                   ; insert packettype into packet
  3879.  add.w   #ether_data,d4             ; d4 = length of header + data
  3880.  
  3881.  
  3882. .send:
  3883. ; Do we have the tag for DMA?
  3884.  lea     bufman_dmacopyfrombuf32(a2),a2
  3885.  move.l  a1,d2                      ; d2 = where to copyfrom
  3886.  move.l  (a2)+,d0
  3887.  beq.s   .nodma
  3888.  
  3889. ; Ask for the DMA address
  3890.  move.l  d0,a1
  3891.  move.l  ios2_data(a3),a0           ; a0=abstract magic cookie ios2_Data
  3892.  jsr     (a1)
  3893.  tst.l   d0                         ; dma possible?
  3894.  move.l  d0,a1
  3895. ; If dma is possible we now have the direct application buffer
  3896. ; in a1.. and we can use that directly with RemoteWrite! cool.
  3897.  ifnd    errordebonly
  3898.  ifd     verbose
  3899.  tst.l   d0
  3900.  beq.s   .v1_nodma
  3901.  bug     <"cnet: using DMA write from $%08lx!",10>,a1
  3902.  tst.l   d0
  3903. .v1_nodma:
  3904.  endc
  3905.  endc
  3906.  bne.s   .copyok                    ; do it with DMA?
  3907.  
  3908.  
  3909. .nodma:
  3910. ; Ohwell, the caller doesn't support DMA transfer, so lets fall
  3911. ; back to regular copyfrom.
  3912.  
  3913.  move.l  d2,a0                      ; a0=to (contiguous)
  3914.  move.l  ios2_data(a3),a1           ; a1=from (abstract)
  3915.  move.l  (a2),a2                    ; get bufman_copyfrombuf
  3916.  move.l  ios2_datalength(a3),d0     ; d0=n
  3917.  jsr     (a2)
  3918.  tst.l   d0
  3919.  beq     .copyfromfail              ; oh fuck.. copyfrombuf failed!
  3920.  
  3921. ; we can return the ioreq now! this helps the tcp/ip stack to reuse
  3922. ; the buffers more efficiently.
  3923.  move.l  a3,a1
  3924.  sub.l   a3,a3
  3925.  bsr     TermIO                     ; finish IOrequest
  3926.  
  3927.  lea     txbuffer+ether_data(pc),a1 ; non-DMA so use txbuffer for copy!!
  3928. .copyok:
  3929.  
  3930.  moveq   #ETHER_MIN_LEN,d0
  3931.  cmp.l   d0,d4
  3932.  bge.s   .min                       ; d4 adjusted to legal packet size
  3933.  move.l  d0,d4
  3934. .min:
  3935.  
  3936.  ifnd    errordebonly
  3937.  ifd     verbose
  3938.  move.l  a1,-(sp)
  3939.  moveq   #0,d1
  3940.  move.w  txbuffer+ether_type(pc),d1
  3941.  bug     <"cnet: wrpkt %08lx%04lx >> %08lx%04lx ">,txbuffer+6(pc),txbuffer+8(pc),txbuffer(pc),txbuffer+2(pc)
  3942.  cmp.w   #1500,d1
  3943.  bhs.s   .type
  3944.  bug     <"(IEEE802.3)len %ld, ">,d1
  3945.  bra.s   .bytes
  3946. .type:
  3947.  bug     <"type %ld, ">,d1
  3948. .bytes:
  3949.  bug     <"%ld bytes",10>,d4
  3950.  moveq   #-ether_data,d0            ; show only the data
  3951.  add.l   d4,d0
  3952.  bsr     showpkt
  3953.  move.l  (sp)+,a1
  3954.  endc
  3955.  endc
  3956.  
  3957.  
  3958. ; copy the transfer buffer to cards memory
  3959.  
  3960.  ; experimental
  3961.  ifgt    0
  3962.  bset    #DDB_TX,dd_flags+1(a5)     ; set our "buffer full" flag
  3963.  bra.s   .trans
  3964.  
  3965. .retrans
  3966.  bug     <"cnet: txintcode: transmit DMA timeout - retry...",10>
  3967.  
  3968. .trans
  3969.  move.w  #TBUF,d0
  3970.  move.w  d4,d1
  3971. ; a1 = txbuffer (or DMA buffer)
  3972.  move.l  a1,-(sp)
  3973.  REMOTEWRITE                        ; put packet into nic tx buffer
  3974.  addq.w  #1,d0
  3975.  move.l  (sp)+,a1
  3976.  beq.s   .retrans
  3977.  
  3978.  else
  3979.  
  3980.  move.w  #TBUF,d0
  3981.  move.w  d4,d1
  3982. ; a1 = txbuffer (or DMA buffer)
  3983.  bset    #DDB_TX,dd_flags+1(a5)     ; set our "buffer full" flag
  3984. ;bsr     RemoteWrite                ; put packet into nic tx buffer
  3985.  REMOTEWRITE
  3986.  addq.w  #1,d0
  3987.  beq.s   .xmiterr
  3988.  
  3989.  endc
  3990.  
  3991.  
  3992. ; now really start the transfer:
  3993.  
  3994.  MYDISABLE                          ; disable interrupts during tx setup
  3995. ;; bset    #DDB_TX,dd_flags+1(a5)     ; set our "buffer full" flag
  3996.  delay
  3997.  move.b  d4,nic_tbcr0               ; set tx byte count lo
  3998.  ror.w   #8,d4
  3999.  delay
  4000.  move.b  d4,nic_tbcr1               ; set tx byte count hi
  4001.  ror.w   #8,d4
  4002.  delay
  4003.  move.b  #DSCM_NODMA|DSCM_TRANS|DSCM_START,nic_cr ; start tx
  4004.  MYENABLE                           ; enable interrupts
  4005.  
  4006. ; update statistics:
  4007.  
  4008.  move.l  dd_tracklist(a5),a0
  4009. .getstats:
  4010.  move.l  (a0),d2                    ; tracking packettypes ?
  4011.  beq.s   .statsdone
  4012.  cmp.l   ss2_ptype(a0),d3           ; stats entry for our type ?
  4013.  beq.s   .gotstats
  4014.  move.l  d2,a0                      ; try next stats entry
  4015.  bra.s   .getstats
  4016.  
  4017. .gotstats:
  4018.  add.l   d4,ss2_stats+s2pts_txbytes(a0)
  4019.  addq.l  #1,ss2_stats+s2pts_txpackets(a0)
  4020. .statsdone:
  4021.  
  4022.  
  4023. .termio:
  4024.  move.l  a3,d0                      ; have we replied it already?
  4025.  beq     .next                      ; we have! process next ioreq
  4026.  
  4027.  move.l  a3,a1
  4028.  bsr     TermIO                     ; finish IOrequest
  4029.  bra     .next                      ; process next ioreq
  4030.  
  4031.  
  4032. .copyfromfail:
  4033.  bug     <"cnet: txintcode: copyfrom returned failure!",10>
  4034. ; note: doesn't get called if a3=0
  4035.  moveq   #S2EVENT_TX|S2EVENT_BUFF,d0
  4036.  bsr     DoEvent
  4037.  clr.l   ios2_datalength(a3)
  4038.  moveq   #S2WERR_BUFF_ERROR,d0
  4039.  move.b  #S2ERR_NO_RESOURCES,io_error(a3)
  4040.  move.l  d0,ios2_wireerror(a3)
  4041.  bra.s   .termio
  4042.  
  4043. .xmiterr:
  4044.  bug     <"cnet: txintcode: transmit DMA timeout!",10>
  4045.  bclr    #DDB_TX,dd_flags+1(a5)     ; clear our "buffer full" flag
  4046.  moveq   #S2EVENT_ERROR|S2EVENT_TX,d0
  4047.  bsr     DoEvent
  4048.  
  4049.  move.l  a3,d0
  4050.  beq     .next                      ; if already replied, process next ioreq
  4051.  
  4052.  clr.l   ios2_datalength(a3)
  4053.  moveq   #S2WERR_GENERIC_ERROR,d0
  4054.  move.b  #S2ERR_TX_FAILURE,io_error(a3)
  4055.  move.l  d0,ios2_wireerror(a3)
  4056.  bra.s   .termio
  4057.  
  4058.  
  4059.  
  4060. ;============================================================
  4061. ;                   rxintcode(device)
  4062. ;                               a1
  4063. ;============================================================
  4064. ;
  4065. ;                service rx interrupts
  4066. ;
  4067. ; scratch: d0-d1, a0-a1, and a5 (softint must preserve a6!)
  4068. ;
  4069. rxintcode:
  4070. ;bug     <"cnet: *** tx int",10>
  4071.  
  4072.  movem.l d6/d7/a6,-(sp)
  4073.  move.l  exec_base(pc),a6
  4074.  move.l  a1,a5                             ; a5 = device
  4075.  
  4076. .nextpage:
  4077.  
  4078.  MYDISABLE
  4079.  delay
  4080.  moveq   #0,d7
  4081.  move.b  #DSCM_NODMA|DSCM_PG1|DSCM_START,nic_cr ; select bank 1
  4082.  move.b  nic_curr,d7                       ; d7 = current page
  4083.  delay
  4084.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr     ; select bank 0
  4085.  MYENABLE
  4086.  
  4087.  moveq   #0,d6
  4088.  delay
  4089.  move.b  nic_bnry,d6
  4090.  addq.w  #1,d6                             ; d6 = next page (boundary+1)
  4091.  cmp.w   #RBUFEND/256,d6
  4092.  blo.s   .nowrap                           ; end of buffer mem  ?
  4093.  moveq   #RBUF/256,d6                      ; wrap around to start
  4094. .nowrap:
  4095.  cmp.w   d6,d7                             ; current page = next page ?
  4096.  beq     .done                             ; if so then nothing to get
  4097.  
  4098.  ifgt    0
  4099.  
  4100.  move.w  d6,d0
  4101.  lea     rx_header(pc),a1                  ; a1 = buffer
  4102.  lsl.w   #8,d0                             ; d0 = 16 bit page address
  4103.  moveq   #prhdr_sizeof+ether_data,d1
  4104.  bsr     RemoteRead                        ; get packet header
  4105.  
  4106.  else
  4107.  
  4108. ; inlined RemoteRead:
  4109.  
  4110.  lea     nic_data,a0
  4111.  lea     rx_header(pc),a1                  ; a1 = buffer
  4112.  ifndef  nocmdsave
  4113.  delay
  4114.  move.b  nic_cr,d1               ; save old command
  4115.  delay
  4116.  endc
  4117.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr ; select bank 0
  4118.  delay
  4119.  ifd     pedanticread
  4120.  move.b  #DSIS_RDC,nic_isr       ;   setup remote dma
  4121.  delay
  4122.  endc
  4123.  move.b  #prhdr_sizeof+ether_data,nic_rbcr0 ;   set count.lo
  4124.  delay
  4125.  move.b  #0,nic_rbcr1            ;   set count.hi
  4126.  delay
  4127.  move.b  #0,nic_rsar0            ;   set address.lo
  4128.  delay
  4129.  move.b  d6,nic_rsar1            ;   set address.hi  (d6=16 bit page address hi)
  4130.  delay
  4131.  move.b  #DSCM_RREAD|DSCM_START,nic_cr ; request Remote Read
  4132.  
  4133.  ; transfer prhdr_sizeof+ether_data = 4+14 = 18 = 2*9
  4134.  
  4135.  ifd     turboio
  4136.  move.l  (a0),(a1)+              ; 4*4 = 16
  4137.  move.l  (a0),(a1)+
  4138.  move.l  (a0),(a1)+
  4139.  move.l  (a0),(a1)+
  4140.  else
  4141.  move.w  (a0),(a1)+              ; 4*4 = 16
  4142.  move.w  (a0),(a1)+
  4143.  move.w  (a0),(a1)+
  4144.  move.w  (a0),(a1)+
  4145.  move.w  (a0),(a1)+
  4146.  move.w  (a0),(a1)+
  4147.  move.w  (a0),(a1)+
  4148.  move.w  (a0),(a1)+
  4149.  endc
  4150.  move.w  (a0),(a1)+              ; +2
  4151.  
  4152.  ifd     pedanticread
  4153.  ; wait till done
  4154.  move.w  #DMATIMEOUT,d0          ; set timeout
  4155. .rd_check:
  4156.  delay
  4157.  btst    #DSIB_RDC,nic_isr       ; wait for remote DMA complete
  4158.  dbne    d0,.rd_check
  4159.  endc
  4160.  
  4161.  move.b  #DSIS_RDC,nic_isr       ; Remote DMA Complete (Ack intr.)
  4162.  ifndef  nocmdsave
  4163.  delay
  4164.  move.b  d1,nic_cr               ; restore old command
  4165.  endc
  4166.  
  4167.  endc
  4168.  
  4169.  ifge    __CPU-68020
  4170.  btst    #0,rx_header+prhdr_status(pc)     ; complete packet received ?
  4171.  else
  4172.  move.b  rx_header+prhdr_status(pc),d0
  4173.  and.b   #DSRS_RPC,d0                      ; complete packet received ?
  4174.  endc
  4175.  bne.s   .goodpacket
  4176.  
  4177.  bug     <"cnet: rxintcode: incomplete packet received",10>
  4178.  addq.l  #1,dd_devicestats+s2ds_baddata(a5) ; count bad packets received
  4179.  bra.s   .next
  4180.  
  4181. .goodpacket:
  4182.  addq.l  #1,dd_devicestats+s2ds_packetsreceived(a5) ; count packets received
  4183.  
  4184.  move.l  a5,a0
  4185.  move.w  d6,d0
  4186. ;lea     rx_header(pc),a1
  4187.  bsr.s   readpacket                        ; feed packet into waiting ioreqs
  4188.  
  4189. .next:
  4190.  moveq   #0,d0
  4191.  move.b  rx_header+prhdr_nxtpg(pc),d0      ; get next page number
  4192.  move.w  d0,d7
  4193.  subq.w  #1,d0                             ; nxtpage-1 = new boundary
  4194.  cmp.w   #RBUF/256,d0
  4195.  bge.s   .boundary                         ; wrap if before 1st page
  4196.  moveq   #(RBUFEND/256)-1,d0
  4197. .boundary:
  4198.  delay
  4199.  move.b  d0,nic_bnry                       ; set new boundary
  4200.  bra     .nextpage                         ; back for more
  4201.  
  4202. .done:
  4203.  delay
  4204.  move.b  #DSCM_NODMA|DSCM_PG0|DSCM_START,nic_cr     ; select bank 0
  4205.  MYDISABLE
  4206.  delay
  4207.  move.b  nic_rsr,d0                        ; read rx status
  4208.  delay
  4209.  move.b  nic_cntr0,d0
  4210.  delay
  4211.  move.b  nic_cntr1,d0                      ; read counters
  4212.  delay
  4213.  move.b  nic_cntr2,d0
  4214.  or.b    #DSIM_OVWE|DSIM_RXEE|DSIM_PRXE,dd_imr(a5)
  4215.  move.b  dd_imr(a5),nic_imr                ; allow rx interrupts
  4216.  MYENABLE
  4217.  
  4218.  movem.l (sp)+,d6/d7/a6
  4219. ;; moveq   #0,d0
  4220.  rts
  4221.  
  4222.  
  4223.  
  4224. ;==============================================================
  4225. ;             readpacket( device, [pkthdr], page )
  4226. ;                           a0     [a1]     d0.w
  4227. ;==============================================================
  4228. ;
  4229. ; get packet from network card and feed it to all different
  4230. ; CMD_READ queues. Also call packet filter before doing the copy.
  4231. ; Note that this is a major improvement to previous implementation,
  4232. ; that only kept one single list of CMD_READs. This finally fixes
  4233. ; sanamon for example.
  4234. ;
  4235. ; Inputs:
  4236. ;
  4237. ;       pkthdr = packet header info extracted from nic
  4238. ;
  4239. ;       page = 256 byte page in nic RAM that holds packet
  4240. ;
  4241. ;
  4242. readpacket:
  4243.  movem.l d2-d7/a2-a6,-(sp)
  4244.  
  4245.  moveq   #0,d6
  4246.  move.w  d0,d7                          ; d7 = page
  4247.  move.l  a0,a5                          ; a5 = device
  4248.  move.b  rx_header+prhdr_sz1(pc),d6
  4249.  moveq   #0,d3
  4250.  lsl.w   #8,d6
  4251.  move.w  rx_header+prhdr_sizeof+ether_type(pc),d3
  4252.  move.b  rx_header+prhdr_sz0(pc),d6
  4253.  lsl.w   #8,d7                          ; address=page*256
  4254.  sub.w   #prhdr_sizeof+ether_data,d6    ; d6 = length of read
  4255.  add.w   #prhdr_sizeof+ether_data,d7    ; skip pageheader and etherheader
  4256.  
  4257. ; dropflag is set to true if at least one protocol stack managed
  4258. ; to get the packet. If this still is zero after the following loop
  4259. ; then I try to feed to for pending S2_READORPHAN request, if any.
  4260.  
  4261.  moveq   #0,d4                          ; dropflag
  4262.  
  4263.  move.l  dd_bufmanlist(a5),a3           ; a3 = first bufman
  4264.  bra.s   .start
  4265.  
  4266. ; scan each CMD_READ callers bufmanlist until we find the ioreq
  4267. ; that want this type of packet or till end of list.
  4268.  
  4269. .nextreq:
  4270.  move.l  (a3),d0
  4271.  beq.s   .nextbufman                    ; end of this CMD_READ list ?
  4272.  cmp.l   ios2_packettype(a3),d3
  4273.  beq.s   .iwantyou                      ; does it want our packet ?
  4274.  cmp.w   #1500,d3
  4275.  bhi.s   .nextnode                      ; accept 802.3 packets
  4276.  cmp.l   #1500,ios2_packettype(a3)
  4277.  bls.s   .iwantyou
  4278. .nextnode:
  4279.  move.l  d0,a3
  4280.  bra.s   .nextreq
  4281.  
  4282. .iwantyou:
  4283. ; a3 = ioreq
  4284.  moveq   #1,d2                          ; use packetfilter
  4285.  bsr     .gotreq
  4286. ; note that we only offer it once per caller!
  4287.  
  4288. .nextbufman:
  4289.  move.l  d5,a3                          ; a3 = next bufman node in list
  4290. .start:
  4291.  move.l  (a3),d5
  4292.  move.l  bufman_rxqueue(a3),a3          ; get pending CMD_READ's list
  4293.  bne.s   .nextreq                       ; end of bufman list ?
  4294.  
  4295. ; Now we've tried to give the packet to every CMD_READ caller,
  4296. ; and d4 contains the number of iorequests that were succesfully
  4297. ; returned. If d4 is 0 at this point no-one wanted this packet.
  4298.  
  4299.  tst.l   d4                             
  4300.  beq.s   .gotdropped                    ; did oneone want it?
  4301.  
  4302. ; Okay, at least one CMD_READ caller got the packet, so we're happy
  4303. ; now and can quit.
  4304.  
  4305. .done:
  4306.  movem.l (sp)+,d2-d7/a2-a6
  4307.  rts
  4308.  
  4309.  
  4310. .gotdropped:
  4311.  
  4312. ; So there were no outstanding CMD_READs or the packet wasn't
  4313. ; accepted by any of them. Okay, check if we have any pending
  4314. ; S2_READORPHAN ioreq in list and if we have return this packet
  4315. ; with it. Note that packet filter must not be used for this
  4316. ; time!
  4317.  
  4318.  addq.l  #1,dd_devicestats+s2ds_unknowntypesreceived(a5)
  4319.  move.l  dd_orphanlist(a5),a3           ; get first S2_READORPHAN available
  4320.  tst.l   (a3)
  4321.  beq.s   .dotrack                       ; got an orphan ioreq ?
  4322.  
  4323. ; d4 = whatever, not important here
  4324. ; a3 = ioreq
  4325.  moveq   #0,d2                          ; indicate S2_READORPHAN call
  4326.  bsr.s   .gotreq
  4327.  
  4328. .dotrack:
  4329.  
  4330. ; Update dropped packet statistics, if requested.
  4331.  
  4332.  move.l  dd_tracklist(a5),a0
  4333. .getstat:
  4334.  move.l  (a0),d0                        ; tracking packettypes ?
  4335.  beq.s   .donetrk
  4336.  cmp.l   ss2_ptype(a0),d3               ; get tracking entry for this type
  4337.  beq.s   .dropped
  4338.  move.l  d0,a0                          ; next tracking entry
  4339.  bra.s   .getstat
  4340. .dropped:
  4341.  addq.l  #1,ss2_stats+s2pts_packetsdropped(a0) ; another packet dropped
  4342. .donetrk:
  4343.  
  4344.  bug     <"cnet: readpacket: packet type %ld dropped",10>,d3
  4345.  
  4346.  moveq   #S2EVENT_ERROR|S2EVENT_RX,d0
  4347.  bsr     DoEvent
  4348.  bra     .done
  4349.  
  4350.  
  4351.  
  4352. .gotreq:
  4353.  
  4354. ; Here we have a ioreq in a3 that has requested packets of this type.
  4355. ; 1st we extract the packet from the card unless we have already done
  4356. ; so. d2 = 0 if this ioreq is S2_READORPHAN call (packetfilter must
  4357. ; not be used). if d2 = 1 then this is a regular CMD_READ and
  4358. ; packetfilter must be called.
  4359.  
  4360.  tst.w   d7
  4361.  beq     .gotalready                    ; have we already read it ?
  4362.  
  4363.  lea     rxbuffer+ether_data(pc),a1
  4364.  move.w  d7,d0                          ; (we only get the user stuff here)
  4365.  move.w  d6,d1
  4366. ;bsr     RemoteRead                     ; get packet user data from nic
  4367.  REMOTEREAD
  4368.  
  4369.  ifnd    errordebonly
  4370.  ifd     verbose
  4371.  bug     <"cnet: readpacket: rdpkt %08lx%04lx < %08lx%04lx, ">,rxbuffer+ether_dest(pc),rxbuffer+ether_dest+2(pc),rxbuffer+ether_src(pc),rxbuffer+ether_src+2(pc)
  4372.  cmp.w   #1500,d3
  4373.  bhi.s   .type
  4374.  bug     <"(IEEE802.3)len %ld, ">,d3
  4375.  bra.s   .bytes
  4376. .type:
  4377.  bug     <"type %ld, ">,d3
  4378. .bytes:
  4379.  moveq   #ether_data,d0
  4380.  add.l   d6,d0
  4381.  bug     <"%ld bytes",10>,d0
  4382.  lea     rxbuffer+ether_data(pc),a1
  4383.  move.l  d6,d0
  4384.  bsr     showpkt
  4385.  endc
  4386.  endc
  4387.  
  4388.  
  4389. ; Update the packet statistics if required.
  4390.  
  4391.  move.l  dd_tracklist(a5),a0
  4392. .getstats:
  4393.  move.l  (a0),d0                        ; tracking packettypes ?
  4394.  beq.s   .received
  4395.  cmp.l   ss2_ptype(a0),d3               ; find stats entry for our type
  4396.  beq.s   .gotstats
  4397.  move.l  d0,a0
  4398.  bra.s   .getstats
  4399. .gotstats:
  4400.  add.l   d6,ss2_stats+s2pts_rxbytes(a0) ; update stats
  4401.  addq.l  #1,ss2_stats+s2pts_rxpackets(a0)
  4402. .received:
  4403.  
  4404.  moveq   #0,d7                          ; don't try to read it from hw anymore
  4405. .gotalready
  4406.  
  4407.  
  4408.  
  4409. ; next figure out if this ioreq asked the raw or non-raw data,
  4410. ; and skip ether_data bytes from the buffer start if it asked
  4411. ; raw.
  4412.  
  4413.  move.l  d6,ios2_datalength(a3)         ; user data size
  4414.  lea     rxbuffer+ether_data(pc),a6     ; a6=user data
  4415.  tst.b   io_flags(a3)                   ; (test SANA2IOB_RAW)
  4416.  bpl.s   .notraw                        ; is etherheader wanted ?
  4417.  add.w   #ether_data+4,ios2_datalength+2(a3) ; raw data size
  4418.  lea     rxbuffer(pc),a6                ; a6=raw data
  4419. .notraw:
  4420.  
  4421. ; now build up the ios2 structure enough so we can call the packet
  4422. ; filter.
  4423.  
  4424.  lea     ios2_dstaddr(a3),a0
  4425.  lea     rxbuffer+ether_dest(pc),a1     ; or: rx_header+prhdr_sizeof+ether_dest
  4426.  move.l  (a1)+,(a0)+                    ; extract the dst address
  4427.  move.w  (a1)+,(a0)+
  4428.  lea     ios2_packettype(a3),a0
  4429.  move.l  d3,(a0)+                       ; packet type
  4430.  move.l  (a1)+,(a0)+                    ; extract the src address
  4431.  move.w  (a1)+,(a0)+
  4432.  
  4433. ; call the packet filter, if available. real men don't use filters. :-)
  4434. ; the truth is out there
  4435.  
  4436.  tst.l   d2
  4437.  move.l  ios2_buffermanagement(a3),a0
  4438.  beq.s   .marlboro                      ; S2_READORPHAN must not use filter!
  4439.  move.l  bufman_packetfilter(a0),d0
  4440.  beq.s   .marlboro                      ; did the caller provide packet filter ?
  4441.  move.l  d0,a0                          ; a0=hook
  4442.  move.l  a6,a1                          ; a1=data
  4443.  move.l  8(a0),a4                       ; h_entry - get hook assembler entry point
  4444.  move.l  a3,a2                          ; a2=ios2
  4445.  jsr     (a4)
  4446.  tst.l   d0
  4447.  beq     .ignore
  4448. .marlboro: ;-!
  4449.  
  4450. ; ok. the packet didn't get filtered, set the BCAST and MCAST
  4451. ; flags according to dstaddr.
  4452.  
  4453.  btst    #0,ios2_dstaddr(a3)            ; address = Multicast ?
  4454.  beq.s   .nmcast
  4455.  cmp.l   #$ffffffff,ios2_dstaddr(a3)
  4456.  bne.s   .nbcast                        ; address = Broadcast ?
  4457.  cmp.w   #$ffff,ios2_dstaddr+4(a3)
  4458.  bne.s   .nbcast
  4459.  bset    #SANA2IOB_BCAST,io_flags(a3)   ; set BROADCAST flag in ioreq
  4460.  bra.s   .nmcast
  4461. .nbcast:
  4462.  bset    #SANA2IOB_MCAST,io_flags(a3)   ; set MULTICAST flag in ioreq
  4463. .nmcast:
  4464.  
  4465. ; finally copy the packet data!
  4466.  
  4467.  move.l  ios2_data(a3),a0
  4468.  move.l  ios2_buffermanagement(a3),a2
  4469.  move.l  a6,a1
  4470.  move.l  bufman_copytobuf(a2),a2
  4471.  move.l  ios2_datalength(a3),d0
  4472.  jsr     (a2)                           ; call copytobuf
  4473.  tst.l   d0
  4474.  beq.s   .copytobuferr
  4475.  
  4476.  addq.l  #1,d4                          ; mark that it wasn't dropped!
  4477.  
  4478.  ifnd    errordebonly
  4479.  ifd     verbose
  4480.  bug     <"cnet: readpacket: copytobuffed packet ior %08lx %08lx%04lx < %08lx%04lx, type %ld, %ld bytes, ">,a3,ios2_dstaddr(a3),ios2_dstaddr+2(a3),ios2_srcaddr(a3),ios2_srcaddr+2(a3),ios2_packettype(a3),ios2_datalength(a3)
  4481.  tst.b   io_flags(a3)
  4482.  bpl.s   .v1
  4483.  bug     <"RAW ">
  4484. .v1:
  4485.  btst    #SANA2IOB_BCAST,io_flags(a3)
  4486.  beq.s   .v2
  4487.  bug     <"BCAST ">
  4488. .v2:
  4489.  btst    #SANA2IOB_MCAST,io_flags(a3)
  4490.  beq.s   .v3
  4491.  bug     <"MCAST ">
  4492. .v3:
  4493.  bug     <10>
  4494.  
  4495.  move.l  a6,a1
  4496.  move.l  ios2_datalength(a3),d0
  4497.  bsr     showpkt
  4498.  
  4499.  endc
  4500.  endc
  4501.  
  4502.  
  4503. .termit:
  4504.  move.l  a3,a1
  4505.  REMOVE                                 ; pull it off the list
  4506.  move.l  a3,a1
  4507.  bra     TermIO                         ; IO finished
  4508.  
  4509.  
  4510. .ignore:
  4511.  bug     <"cnet: readpacket: packet type %ld for %08lx ior filtered",10>,d3,a3
  4512.  
  4513. ; the packet got rejected by packet filter!
  4514.  rts
  4515.  
  4516.  
  4517. .copytobuferr:
  4518. ; oh fuck.. copytobuf failed!
  4519.  bug     <10,"cnet: readpacket: copytobuf returned failure!",10>
  4520.  
  4521.  moveq   #S2EVENT_RX|S2EVENT_BUFF,d0
  4522.  bsr     DoEvent
  4523.  clr.l   ios2_datalength(a3)
  4524.  moveq   #S2WERR_BUFF_ERROR,d0
  4525.  move.b  #S2ERR_NO_RESOURCES,io_error(a3)
  4526.  move.l  d0,ios2_wireerror(a3)
  4527.  bra.s   .termit
  4528.  
  4529.  
  4530.  
  4531.  
  4532. ;======================================================================
  4533. ;                  init_card(flags, device)
  4534. ;                             d0.l    a1
  4535. ;======================================================================
  4536. ;
  4537. ;                    Initialise PCMCIA card
  4538. ;
  4539. ; flags:
  4540. ;   bit 0: if set don't display easyreq
  4541. ;
  4542. init_card:
  4543.  ifnd    errordebonly
  4544.  bug     <"cnet: init_card",10>
  4545.  endc
  4546.  
  4547.  movem.l d3-d6/a3/a6,-(sp)
  4548.  move.l  d0,d6
  4549.  move.l  a1,a3                        ; a3 = device
  4550.  move.l  dd_cardres(a3),a6
  4551.  
  4552.  btst    #DDB_CARDHANDLE,dd_flags+1(a3)   ; do we own the card already?
  4553.  bne     .owned
  4554.  
  4555.  lea     dd_cardhandle(a3),a1
  4556.  
  4557.  lea     dd_cardremoved(a3),a0        ; init interrupt for card removed
  4558.  move.l  a3,is_data(a0)
  4559.  move.l  #card_removed_code,is_code(a0)
  4560.  move.l  a0,cah_CardRemoved(a1)
  4561.  
  4562.  lea     dd_cardinserted(a3),a0       ; init interrupt for card inserted
  4563.  move.l  a3,is_data(a0)
  4564.  move.l  #card_inserted_code,is_code(a0)
  4565.  move.l  a0,cah_CardInserted(a1)
  4566.  
  4567.  lea     dd_cardstatus(a3),a0         ; init interrupt for status change
  4568.  move.l  a3,is_data(a0)
  4569.  
  4570.  cmp.w   #39,LIB_VERSION(a6)          ; got CARDB_POSTSTATUS (v39+) ?
  4571.  blo.s   .oldie
  4572.  
  4573.  move.l  #status_int_code_v39,is_code(a0)
  4574.  move.b  #CARDF_IFAVAILABLE|CARDF_POSTSTATUS,cah_cardflags(a1)
  4575.  bra.s   .was_goldie
  4576.  
  4577. .oldie:
  4578.  move.l  #status_int_code_v37,is_code(a0)
  4579.  move.b  #CARDF_IFAVAILABLE,cah_cardflags(a1)
  4580. .was_goldie:
  4581.  move.l  a0,cah_CardStatus(a1)
  4582.  
  4583.  lea     devicename(pc),a0
  4584.  move.l  a0,ln_name(a1)
  4585.  move.b  #20,ln_pri(a1)               ; high priority for I/O card
  4586.  
  4587.  jsr     _LVOOwnCard(a6)              ; own card (sets up interrupt vectors)
  4588.  tst.l   d0
  4589.  bne     .error1
  4590.  
  4591.  or.w    #DDF_CARDHANDLE,dd_flags(a3)   ; card is inserted & owned by us
  4592.  
  4593. .owned:
  4594. ; allocate PCMCIA tuple buffer from stack
  4595.  lea     -48(sp),sp
  4596.  
  4597.  moveq   #CISTPL_FUNC_ID,d1
  4598.  bsr     .copytuple                   ; read function tuple
  4599.  beq.s   .assume_network_card         ; did we get one? if not assume it's a network card... (Neil Cafferkey)
  4600.  
  4601.  cmp.b   #CISTPL_FUNCID_NETWORK,2(sp)  ; *if* function tuple is found it
  4602.  bne     .err2                         ; must be a network card!
  4603. .assume_network_card:
  4604.  
  4605.  moveq   #CISTPL_CONF_MAP,d1          
  4606.  bsr     .copytuple                   ; read config map tuple
  4607.  beq.s   .error3
  4608.  
  4609.  moveq   #$03,d0
  4610.  moveq   #0,d5
  4611.  and.b   2(sp),d0                     ; (number of address bytes)-1
  4612.  
  4613. ;bug     <"init_card: tuple[2] & 0x3 = %ld",10>,d0
  4614. .getaddr:
  4615. ;bug     <"init_card: r = %ld",10>,d0
  4616.  lsl.l   #8,d5
  4617.  move.b  4(sp,d0.l),d5                ; extract config register address
  4618.  subq.l  #1,d0
  4619.  bpl.s   .getaddr
  4620.  and.l   #$0001FFFF,d5                ; limit to attribute memory range
  4621.  
  4622.  bug     <"init_card: config address: $%08lx",10>,d5
  4623.  
  4624.  moveq   #CISTPL_CONFIG,d1
  4625.  bsr     .copytuple                   ; read 1st config tuple
  4626.  beq.s   .error4
  4627.  
  4628.  lea     dd_cardhandle(a3),a1
  4629.  moveq   #CARD_DISABLEF_WP|CARD_ENABLEF_DIGAUDIO,d1
  4630.  jsr     _LVOCardMiscControl(a6)      ; enable card I/O functions
  4631.  
  4632.  moveq   #$3f,d0
  4633.  lea     AttrMem,a0
  4634.  and.b   2(sp),d0                     ; extract configuration ID value & mask ID out of it
  4635.  add.l   d5,a0
  4636.  bug     <"cnet: ID: %ld card config register: $%08lx",10>,d0,a0
  4637.  move.b  d0,(a0)                      ; put ID into card config register
  4638.  
  4639.  lea     48(sp),sp                    ; deallocate PCMCIA tuple buffer
  4640.  
  4641.  ifnd    errordebonly
  4642.  bug     <"cnet: init_card: OK",10>
  4643.  endc
  4644.  moveq   #0,d0                        ; card is active, return OK
  4645.  
  4646. .done:
  4647.  movem.l (sp)+,d3-d6/a3/a6
  4648.  rts
  4649.  
  4650. .copytuple
  4651.  lea     dd_cardhandle(a3),a1
  4652.  lea     4(sp),a0                     ; tuple buffer in stack
  4653.  moveq   #40,d0
  4654.  jsr     _LVOCopyTuple(a6)
  4655.  tst.l   d0
  4656.  rts
  4657.  
  4658.  
  4659. .error1:
  4660.  bug     <"cnet: init_card: OwnCard() failed",10>
  4661.  
  4662. .err
  4663.  moveq   #S2EVENT_ERROR|S2EVENT_HARDWARE,d0
  4664.  bsr     DoEvent
  4665.  moveq   #-1,d0                       ; card not available, return error
  4666.  bra.s   .done
  4667.  
  4668. .error3:
  4669.  bug     <"cnet: init_card: CISTPL_CONF_MAP tuple not found",10>
  4670.  lea     .errmsg3(pc),a0
  4671. .easyreq_err2:
  4672.  btst    #0,d6
  4673.  bne.b   .noreq
  4674.  bsr     EasyReq
  4675. .noreq
  4676.  
  4677. .err2
  4678.  lea     48(sp),sp                    ; deallocate PCMCIA tuple buffer
  4679.  bra.s   .err
  4680.  
  4681. .error4:
  4682.  bug     <"cnet: init_card: CISTPL_CONFIG tuple not found",10>
  4683.  lea     .errmsg4(pc),a0
  4684.  bra.s   .easyreq_err2
  4685.  
  4686.  
  4687. .errmsg3:
  4688.  dc.b    "CISTPL_CONF_MAP tuple not found",0
  4689.  
  4690. .errmsg4:
  4691.  dc.b    "CISTPL_CONFIG tuple not found",0
  4692.  
  4693.  CNOP    0,2
  4694.  
  4695.  
  4696.  
  4697. ;============================================================
  4698. ;             PCMCIA status change interrupt
  4699. ;============================================================
  4700. ;
  4701. ;   Occurs whenever a PCMCIA status line changes
  4702. ;
  4703. ;   eg. when the network card activates it's interrupt line
  4704. ;
  4705. ;
  4706. ;  entry:   d0 = status change(s)
  4707. ;           a1 = device
  4708. ;
  4709. ;  exit:    d0 must be preserved!
  4710. ;
  4711.  
  4712. STATINT MACRO
  4713.  
  4714.  btst    #DDB_NICUP,dd_flags+1(a1)  ; is nic working ?
  4715.  beq     .done
  4716.  
  4717.  movem.l d2-d6/a2-a4,-(sp)
  4718.  move.l  a1,a4                      ; a4 = device
  4719.  move.l  d0,d6                      ; d6 = status changes
  4720.  move.l  exec_base(pc),a6
  4721.  
  4722.  ifndef  nocmdsave
  4723.  move.b  nic_cr,d5                  ; save old command
  4724.  delay
  4725.  endc
  4726.  move.b  #0,nic_imr                 ; prevent nic interrupts
  4727.  bra     .checkint
  4728.  
  4729. ; interrupt service loop    (d3 = interrupt status)
  4730.  
  4731. .intloop:
  4732.  btst    #DSIB_ROVRN,d3             ; Overwrite warning enable ?
  4733.  beq     .no_overflow
  4734. ; receiver ring buffer overflowed (eek!)
  4735.  bug     <"cnet: status_int: receiver ring buffer overflow",10>
  4736.  ;;unused counter
  4737.  ;;addq.l  #1,dd_overflows(a4)
  4738.  delay
  4739.  move.b  #0,nic_rbcr0
  4740.  delay
  4741.  move.b  #0,nic_rbcr1               ; reset remote byte count
  4742.  delay
  4743.  move.b  #DSRC_MON,nic_rcr          ; monitor mode
  4744.  delay
  4745.  move.b  #DSTC_LB0,nic_tcr          ; set tx to loopback mode 1
  4746.  delay
  4747.  move.b  #DSCM_NODMA|DSCM_START,nic_cr ; try to restart controller
  4748.  delay
  4749.  ;;;FIXED, WAS: move.b  #DSRC_AB,nic_rcr
  4750.  move.b  dd_rcr(a4),nic_rcr         ; normal rx mode
  4751.  delay
  4752.  move.b  #DEF_TCR,nic_tcr           ; tx loopback mode off
  4753. .no_overflow:
  4754.  
  4755.  btst    #DSIB_RXE,d3               ; Receive error enable ?
  4756.  beq.s   .norxerr
  4757.  bug     <"cnet: status_int: packet receive error",10>
  4758.  addq.l  #1,dd_devicestats+s2ds_baddata(a4) ; another bad rx packet ?
  4759.  delay
  4760.  move.b  nic_rsr,d0                 ; read rx status
  4761.  delay
  4762.  move.b  nic_cntr0,d0
  4763.  delay
  4764.  move.b  nic_cntr1,d0               ; read counters
  4765.  delay
  4766.  move.b  nic_cntr2,d0
  4767.  bra.s   .rx
  4768. .norxerr:
  4769.  
  4770.  btst    #DSIB_RX,d3                ; Packet received enable ?
  4771.  beq.s   .no_rx
  4772.  
  4773. ; new packet(s) arrived in receive ring buffer
  4774. .rx:
  4775.  and.b   #~(DSIM_OVWE|DSIM_RXEE|DSIM_PRXE),dd_imr(a4) ; ignore rx ints
  4776.  lea     dd_rxint(a4),a1
  4777.  jsr     _LVOCause(a6)              ; to copy packet(s) into waiting ioreq(s)
  4778. .no_rx:
  4779.  
  4780.  ; experimental
  4781.  ifgt    0
  4782.  
  4783.  btst    #DSIB_TXE,d3               ; Transmit error enable ?
  4784.  beq.s   .no_txe
  4785. ; error occured while sending packet
  4786.  bug     <"cnet: status_int: packet transmit error",10>
  4787.  bclr    #DDB_TX,dd_flags+1(a4)     ; buffer now free
  4788.  moveq   #0,d0
  4789.  delay
  4790.  move.b  nic_ncr,d0                 ; read collision count
  4791.  add.l   d0,dd_retries(a4)          ; increment retry count
  4792. .no_txe
  4793.  
  4794.  btst    #DSIB_TX,d3                ; Packet transmitted enable ?
  4795.  beq     .no_tx
  4796. ; a packet has just been transmitted
  4797.  bclr    #DDB_TX,dd_flags+1(a4)     ; buffer now free
  4798.  moveq   #0,d0
  4799.  delay
  4800.  move.b  nic_ncr,d0                 ; read collision count
  4801.  addq.l  #1,dd_devicestats+s2ds_packetssent(a4) ; count packets sent
  4802.  add.l   d0,dd_retries(a4)          ; increment retry count
  4803.  lea     dd_txint(a4),a1
  4804.  jsr     _LVOCause(a6)              ; to transmit next packet
  4805. .no_tx:
  4806.  
  4807.  else
  4808.  
  4809.  moveq   #DSIS_TXE|DSIS_TX,d0
  4810.  and.b   d3,d0
  4811.  beq.s   .no_tx
  4812.  
  4813. ; a packet has just been transmitted / failed to transmit
  4814.  bclr    #DDB_TX,dd_flags+1(a4)     ; buffer now free
  4815.  moveq   #0,d0
  4816.  delay
  4817.  move.b  nic_ncr,d0                 ; read collision count
  4818.  addq.l  #1,dd_devicestats+s2ds_packetssent(a4) ; count packets sent
  4819.  add.l   d0,dd_retries(a4)          ; increment retry count
  4820.  lea     dd_txint(a4),a1
  4821.  jsr     _LVOCause(a6)              ; to transmit next packet
  4822. .no_tx:
  4823.  
  4824.  endc
  4825.  
  4826.  btst    #DSIB_CTRS,d3              ; counter overflow ?
  4827.  beq.s   .nocounter
  4828.  
  4829. ; counter overflow
  4830.  delay
  4831.  move.b  nic_cntr0,d0
  4832.  delay
  4833.  move.b  nic_cntr1,d0               ; read counters
  4834.  delay
  4835.  move.b  nic_cntr2,d0
  4836. .nocounter:
  4837.  
  4838.  
  4839. .checkint:
  4840.  delay
  4841.  move.b  nic_isr,d3                 ; d3 = nic interrupt status
  4842.  delay
  4843.  move.b  d3,nic_isr                 ; clear current interrupt bit(s)
  4844.  and.b   dd_imr(a4),d3
  4845.  bne     .intloop                   ; any valid interrupts ?
  4846.  
  4847.  ifndef  nocmdsave
  4848.  delay
  4849.  move.b  d5,nic_cr                  ; restore old command
  4850.  endc
  4851.  
  4852.  ENDM
  4853.  
  4854.  
  4855.  
  4856.  CNOP    0,4
  4857. status_int_code_v37:
  4858. ;bug     <"cnet: ***statusint_v37 mask: 0x%08lx base: 0x%08lx",10>,d0,a1
  4859.  
  4860.  STATINT
  4861.  
  4862.  eor.b   #$2c,d6
  4863.  or.b    #$c0,d6
  4864.  move.b  d6,$da9000                 ; clear PCMCIA status change bits
  4865.  delay
  4866.  move.b  dd_imr(a4),nic_imr         ; enable nic interrupts
  4867.  moveq   #0,d0                      ; don't clear status bits coz we did
  4868.  
  4869.  movem.l (sp)+,d2-d6/a2-a4
  4870. .done:
  4871.  rts
  4872.  
  4873.  
  4874.  CNOP    0,4
  4875. status_int_code_v39:
  4876. ;bug     <"cnet: ***statusint_v39 mask: 0x%08lx base: 0x%08lx",10>,d0,a1
  4877.  
  4878.  STATINT
  4879.  
  4880.  delay
  4881.  move.b  dd_imr(a4),nic_imr         ; enable nic interrupts
  4882.  move.l  d6,d0                      ; return original d0
  4883.  
  4884. ;bug     <"cnet: statusint_v39 exit: 0x%08lx",10>,d0
  4885.  
  4886.  movem.l (sp)+,d2-d6/a2-a4
  4887. .done:
  4888.  rts
  4889.  
  4890.  
  4891.  
  4892. ;============================================================
  4893. ;             PCMCIA Card Inserted interrupt
  4894. ;============================================================
  4895. ;
  4896. ;   Occurs whenever a PCMCIA card is plugged in
  4897. ;
  4898. ; NOTE: card.resource has given us ownership of the card
  4899. ;
  4900. ;  entry: a1 = device
  4901. ;
  4902. ;  exit:  d0,d1,a0,a1,a5,a6 = scratch
  4903. ;
  4904. card_inserted_code:
  4905.  ifnd    errordebonly
  4906.  bug     <"cnet: PCMCIA card inserted",10>
  4907.  endc
  4908.  
  4909.  tst.w   lib_opencnt(a1)               ; is someone interested about cards ?
  4910.  beq.s   .done
  4911.  
  4912.  move.l  a1,a5
  4913.  
  4914.  moveq   #1,d0                         ; quiet, no easyreq
  4915.  bsr     init_card
  4916.  tst.l   d0                            ; attempt to init pcmcia card
  4917.  bne.s   .releasecard
  4918.  
  4919.  move.l  a5,a1
  4920.  moveq   #1,d0                         ; quiet, no easyreq
  4921.  bsr     init_nic                      ; attempt to start controller
  4922.  tst.l   d0
  4923.  beq.s   .good
  4924.  
  4925. .releasecard:
  4926.  move.l  dd_cardres(a5),a6
  4927.  lea     dd_cardhandle(a5),a1
  4928.  moveq   #0,d0
  4929.  jsr     _LVOReleaseCard(a6)           ; release foreign or bad card
  4930.  bra.s   .done
  4931.  
  4932. .good:
  4933.  btst    #DDB_OFFLINE,dd_flags+1(a5)   ; has device been put offline ?
  4934.  bne.s   .done
  4935.  bset    #DDB_ONLINE,dd_flags+1(a5)    ; device is now online
  4936.  moveq   #S2EVENT_ONLINE,d0
  4937.  bra     DoEvent                       ; return ONLINE event
  4938.  
  4939. .done:
  4940.  rts
  4941.  
  4942.  
  4943.  
  4944. ;============================================================
  4945. ;             PCMCIA Card Removed interrupt
  4946. ;============================================================
  4947. ;
  4948. ;   Occurs whenever a PCMCIA card is unplugged
  4949. ;
  4950. ;  entry: a1 = device
  4951. ;
  4952. ;  exit:  d0,d1,a0,a1,a5,a6 = scratch
  4953. ;
  4954. card_removed_code:
  4955.  ifnd    errordebonly
  4956.  bug     <"cnet: PCMCIA card removed",10>
  4957.  endc
  4958.  
  4959.  and.w   #~(DDF_ONLINE|DDF_NICUP),dd_flags(a1)
  4960.  move.l  dd_cardres(a1),a6
  4961.  lea     dd_cardhandle(a1),a1
  4962.  moveq   #0,d0
  4963.  jsr     _LVOReleaseCard(a6)            ; release card
  4964.  
  4965.  moveq   #S2EVENT_OFFLINE,d0
  4966.  bra     DoEvent                        ; return OFFLINE event
  4967.  
  4968.  
  4969.  
  4970. ; debugging stuff...
  4971.  
  4972.  ifnd    errordebonly
  4973.  ifd     verbose
  4974. showpkt:
  4975.  movem.l a0-a1/d0-d2,-(sp)
  4976.  bug     <10>
  4977.  moveq   #0,d1
  4978.  
  4979. .rows:
  4980.  moveq   #15,d2
  4981.  lea     .string(pc),a0
  4982.  
  4983. .bytes:
  4984.  move.b  (a1)+,d1
  4985.  cmp.b   #' ',d1
  4986.  blo.s   .dot
  4987.  cmp.b   #'z',d1
  4988.  bhs.s   .dot
  4989.  move.b  d1,(a0)+
  4990.  bra.s   .ends
  4991. .dot:
  4992.  move.b  #'.',(a0)+
  4993. .ends:
  4994.  move.b  #0,(a0)
  4995.  bug     <"%02lx ">,d1
  4996.  subq.w  #1,d0
  4997.  beq.s   .end
  4998.  dbf     d2,.bytes
  4999.  bra.s   .shows
  5000.  
  5001. .endspc:
  5002.  bug     <"   ">
  5003. .end:
  5004.  dbf     d2,.endspc
  5005.  
  5006. .shows:
  5007.  bug     <"  %s",10>,#.string
  5008.  tst.w   d0
  5009.  bne.s   .rows
  5010.  
  5011.  bug     <10,10>
  5012.  movem.l (sp)+,a0-a1/d0-d2
  5013.  rts
  5014.  
  5015. .string:
  5016.  ds.b    16
  5017.  dc.b    0
  5018.  even
  5019.  endc
  5020.  endc
  5021.  
  5022.  
  5023. ;============================================================
  5024. ;        MemPool routines with pre-V39 compatiblity
  5025. ;============================================================
  5026. ;
  5027. ; standard code, snipped from somewhere... ;-)
  5028. ;
  5029.  
  5030. createpool    cmp.w    #39,(LIB_VERSION,a6)
  5031.     bcs.b    .createpool
  5032.     jmp    (_LVOCreatePool,a6)
  5033.  
  5034. .createpool    sub.l    a0,a0
  5035.     cmp.l    d2,d1
  5036.     bcs.b    .err
  5037.     move.l    d0,-(sp)
  5038.     moveq    #MEM_BLOCKMASK,d0
  5039.     add.l    d0,d1
  5040.     not.b    d0
  5041.     and.b    d0,d1
  5042.     move.l    d1,-(sp)
  5043.     moveq    #0,d1
  5044.     moveq    #24,d0
  5045.     jsr    (_LVOAllocMem,a6)
  5046.     move.l    (sp)+,d1
  5047.     move.l    (sp)+,a0
  5048.     tst.l    d0
  5049.     beq.b    .nomem
  5050.     exg    d0,a0
  5051.     move.l    a0,(8,a0)
  5052.     addq.l    #4,a0
  5053.     clr.l    (a0)
  5054.     move.l    a0,-(a0)
  5055.     lea    (12,a0),a1
  5056.     move.l    d0,(a1)+
  5057.     move.l    d1,(a1)+
  5058.     move.l    d2,(a1)+
  5059. .err    move.l    a0,d0
  5060. .nomem
  5061. p_rts    rts
  5062.  
  5063.  
  5064. deletepool    cmp.w    #39,(LIB_VERSION,a6)
  5065.     bcs.b    .deletepool
  5066.     jmp    (_LVODeletePool,a6)
  5067.  
  5068. .deletepool    move.l    a0,d0
  5069.     beq.b    p_rts
  5070.  
  5071.     movem.l    d2/a2,-(sp)
  5072.     move.l    (a0),a2
  5073. .loop    move.l    (a2),d2
  5074.     beq.b    .done
  5075.     move.l    a2,a1
  5076.     move.l    d2,a2
  5077.     move.l    -(a1),d0
  5078.     jsr    (_LVOFreeMem,a6)
  5079.     bra.b    .loop
  5080.  
  5081. .done    move.l    a2,a1
  5082.     subq.l    #4,a1
  5083.     movem.l    (sp)+,d2/a2
  5084.     moveq    #24,d0
  5085.     jmp    (_LVOFreeMem,a6)
  5086.  
  5087.  
  5088. ;  IN: d0 = memSize
  5089. ; OUT: d0 = memory, or NULL
  5090.     CNOP    0,4
  5091. alloc:    lea    poolsema(pc),a0
  5092.     jsr    _LVOObtainSemaphore(a6)
  5093.  
  5094.     move.l    poolptr(pc),a0
  5095.     bsr.s    allocpooled
  5096.  
  5097.     lea    poolsema(pc),a0
  5098.     jmp    _LVOReleaseSemaphore(a6)
  5099.  
  5100.  
  5101.     CNOP    0,4
  5102. allocpooled    cmp.w    #39,(LIB_VERSION,a6)
  5103.     bcs.b    .allocpooled
  5104.     jmp    (_LVOAllocPooled,a6)
  5105.  
  5106. .allocpooled    move.l    d0,d1
  5107.     beq.b    .exit
  5108.     move.l    a0,d0
  5109.     beq.b    .exit
  5110.  
  5111.     movem.l    d2/d3/a2/a3,-(sp)
  5112.     move.l    d1,d2
  5113.     move.l    a0,a2
  5114.     cmp.l    (20,a2),d2
  5115.     bcc.b    .nofree
  5116. .allocouter    move.l    (a2),d3
  5117. .allocinner    move.l    d3,a3
  5118.     move.l    (a3),d3
  5119.     beq.b    .alloc
  5120.     move.l    a3,a0
  5121.     tst.l    (8,a0)
  5122.     beq.b    .alloc
  5123.     move.l    d2,d0
  5124.     jsr    (_LVOAllocate,a6)
  5125.     tst.l    d0
  5126.     beq.b    .allocinner
  5127.  
  5128.     btst    #MEMB_CLEAR-16,(12+2,a2)
  5129.     beq.b    .noclr
  5130.     move.l    d2,d1
  5131.     move.l    d0,a1
  5132.     addq.l    #MEM_BLOCKMASK,d1
  5133.     lsr.l    #3,d1
  5134. .clr    clr.l    (a1)+
  5135.     clr.l    (a1)+
  5136.     subq.l    #1,d1
  5137.     bne.b    .clr
  5138. .noclr
  5139. .nomem    movem.l    (sp)+,d2/d3/a2/a3
  5140. .exit    rts
  5141.  
  5142. .nofree    moveq    #8+4,d0
  5143.     move.l    (12,a2),d1
  5144.     add.l    d2,d0
  5145.     bsr    .allocvec
  5146.     beq.b    .nomem
  5147.  
  5148.     move.l    d0,a1
  5149.     move.l    a2,a0
  5150.     addq.l    #4,a0
  5151.     move.l    (4,a0),d0
  5152.     move.l    a1,(4,a0)
  5153.     exg    d0,a0
  5154.     movem.l    d0/a0,(a1)
  5155.     move.l    a1,(a0)
  5156.     addq.l    #8,a1
  5157.     clr.l    (a1)+
  5158.     move.l    a1,d0
  5159.     bra.b    .nomem
  5160.  
  5161. .alloc    moveq    #36,d0
  5162.     move.l    (12,a2),d1
  5163.     add.l    (16,a2),d0
  5164.     bsr.b    .allocvec
  5165.     beq.b    .nomem
  5166.  
  5167.     move.l    d0,a3
  5168.     move.l    d0,a1
  5169.     move.l    a2,a0
  5170.     move.l    (a0),d0
  5171.     move.l    a1,(a0)
  5172.     movem.l    d0/a0,(a1)
  5173.     move.l    d0,a0
  5174.     move.l    a1,(LN_PRED,a0)
  5175.     lea    (.poolname,pc),a0
  5176.     move.w    #(10<<8)|10,(LN_TYPE,a3)  ; LN_TYPE=NT_MEMORY LN_PRI=10
  5177.     move.l    a0,(LN_NAME,a3)
  5178.     move.w    (12+2,a2),(MH_ATTRIBUTES,a3)
  5179.     lea    (MH_SIZE+4,a3),a0
  5180.     moveq    #-MEM_BLOCKSIZE,d1    ;move.l #~MEM_BLOCKMASK,d1
  5181.     move.l    a0,d0
  5182.     and.l    d0,d1
  5183.     move.l    d1,a0
  5184.     move.l    (16,a2),d0
  5185.     move.l    a0,(MH_FIRST,a3)
  5186.     move.l    a0,(MH_LOWER,a3)
  5187.     move.l    d0,(MH_FREE,a3)
  5188.     clr.l    (a0)
  5189.     move.l    d0,(4,a0)
  5190.     add.l    d0,a0
  5191.     move.l    a0,(MH_UPPER,a3)
  5192.     bra.w    .allocouter
  5193.  
  5194. .allocvec    addq.l    #4,d0
  5195.     move.l    d0,-(sp)
  5196.     jsr    (_LVOAllocMem,a6)
  5197.     move.l    (sp)+,d1
  5198.     tst.l    d0
  5199.     beq.b    .av_nomem
  5200.     move.l    d0,a0
  5201.     addq.l    #4,d0
  5202.     move.l    d1,(a0)+
  5203. .av_nomem    rts
  5204.  
  5205. .poolname:
  5206.     dc.b    'Pool',0
  5207.     CNOP    0,2
  5208.  
  5209.  
  5210. ;  IN: a1 = memory
  5211. ;      d0 = memSize
  5212. ; OUT: -
  5213.     CNOP    0,4
  5214. free:    lea    poolsema(pc),a0
  5215.     jsr    _LVOObtainSemaphore(a6)
  5216.  
  5217.     move.l    poolptr(pc),a0
  5218.     bsr.s    freepooled
  5219.  
  5220.     lea    poolsema(pc),a0
  5221.     jmp    _LVOReleaseSemaphore(a6)
  5222.  
  5223.  
  5224.     CNOP    0,4
  5225. freepooled    cmp.w    #39,(LIB_VERSION,a6)
  5226.     bcs.b    .freepooled
  5227.     jmp    (_LVOFreePooled,a6)
  5228.  
  5229. .freepooled    move.l    a0,d1
  5230.     beq.b    .exit
  5231.     move.l    a1,d1
  5232.     beq.b    .exit
  5233.     cmp.l    (20,a0),d0
  5234.     bcc.b    .big_free
  5235.     move.l    a3,-(sp)
  5236.     move.l    (a0),d1
  5237. .findmem    move.l    d1,a3
  5238.     move.l    (a3),d1
  5239.     beq.b    .nomem
  5240.     tst.l    (LN_TYPE,a3)
  5241.     beq.b    .nomem
  5242.     cmp.l    (MH_LOWER,a3),a1
  5243.     bcs.b    .findmem
  5244.     cmp.l    (MH_UPPER,a3),a1
  5245.     bcc.b    .findmem
  5246.     move.l    a3,a0
  5247.     jsr    (_LVODeallocate,a6)
  5248.     move.l    (LN_PRED,a3),a1
  5249.     move.l    (LN_PRED,a1),d1
  5250.     beq.b    .nope
  5251.     move.l    d1,a0
  5252.     move.l    a3,(a0)
  5253.     move.l    a0,(LN_PRED,a3)
  5254.     move.l    a3,(LN_PRED,a1)
  5255.     move.l    (a3),a0
  5256.     move.l    a0,(a1)
  5257.     move.l    a1,(LN_PRED,a0)
  5258.     move.l    a1,(a3)
  5259. .nope    move.l    a3,a1
  5260.     move.l    (sp)+,a3
  5261.     move.l    (MH_FREE,a1),d0        ; was MH_SIZE (bug!)
  5262.     add.l    (MH_LOWER,a1),d0
  5263.     sub.l    (MH_UPPER,a1),d0
  5264.     beq.b    .free
  5265. .exit    rts
  5266.  
  5267. .big_free    subq.l    #4,a1
  5268.     subq.l    #8,a1
  5269. .free    move.l    a1,d0
  5270.     move.l    (a1)+,a0
  5271.     move.l    (a1),a1
  5272.     move.l    a0,(a1)
  5273.     move.l    a1,(4,a0)
  5274.     move.l    d0,a1
  5275.     move.l    -(a1),d0
  5276.     jmp    (_LVOFreeMem,a6)
  5277.  
  5278. .nomem    move.l    (sp),a3
  5279.     move.l    d7,(sp)
  5280.     move.l    #$0100000F,d7
  5281.     jsr    (_LVOAlert,a6)
  5282.     move.l    (sp)+,d7
  5283.     rts
  5284.  
  5285.  
  5286.  
  5287. ;--------------------------------------------------------
  5288. ;                  Global constant data
  5289. ;--------------------------------------------------------
  5290. ;
  5291.  
  5292. rxintname:
  5293.  dc.b "cnet rx softint",0
  5294. txintname:
  5295.  dc.b "cnet tx softint",0
  5296.  
  5297. cardname:
  5298.  dc.b "card.resource",0
  5299. timerdevname:
  5300.  dc.b "timer.device",0
  5301. utilityName:
  5302.  dc.b "utility.library",0
  5303.  
  5304. multiname:
  5305.  dc.b "bad multicasts",0
  5306. retryname:
  5307.  dc.b "retries",0
  5308.  
  5309. DeviceName:
  5310.  dc.b    "cnet.device",0
  5311.  
  5312.  
  5313.  dc.b    "$VER: "
  5314. IDString:
  5315.  dc.b    "cnet.device "
  5316.  VERSTR
  5317.  ifeq    __CPU-68000
  5318.  dc.b    " 68000+"
  5319.  else
  5320.  ifge    __CPU-68020
  5321.  dc.b    " 68020+"
  5322.  endc
  5323.  endc
  5324.  ifd     turboio
  5325.  dc.b    "/turboio"
  5326.  endc
  5327.  ifd     debug
  5328.  dc.b    "/debug"
  5329.  endc
  5330.  dc.b    " by Harry ",34,"Piru",34," Sintonen",10,0
  5331.  
  5332.  
  5333. ; devicequery block
  5334.  
  5335.  CNOP 0,2
  5336. size_supplied:
  5337.  dc.l    S2DQ_SIZE            ; bytes supplied (size of this block)
  5338.  dc.l    0                    ; this is type 0
  5339.  dc.l    0                    ; this document is level 0
  5340.  dc.w    ETHER_ADDR_SIZE*8    ; address size in bits
  5341.  dc.l    ETHERPKT_SIZE        ; maximum packet data size
  5342.  dc.l    10000000             ; line rate (10 Megabits/sec)
  5343.  dc.l    S2WIRETYPE_ETHERNET  ; what the wire is
  5344.  
  5345.  
  5346. ; default station address to use if the card won't give it to us.
  5347.  
  5348.  CNOP 0,2
  5349. default_address:
  5350.  dc.b    $00,$00,$12,$34,$56,$78 ; replace this with your card's address!
  5351.  
  5352.  
  5353. ;--------------------------------------------------------
  5354. ;                      Global data
  5355. ;--------------------------------------------------------
  5356. ;
  5357. ; linked with phxlnk so no need for separate bss hunk!
  5358. ; section buffers,bss
  5359. ;
  5360. ; here for easy & fast access (no need to go thru device ptr)
  5361.  
  5362.  CNOP 0,4
  5363. exec_base:     ds.l  1       ; local copy of execbase
  5364. me_myself:     ds.l  1       ; pointer to this device itself
  5365. poolptr:       ds.l  1       ; pointer to memory pool
  5366. poolsema:      ds.b  SS_SIZE ; semaphore for mempool arbitration
  5367.  
  5368.  
  5369.  CNOP 0,8
  5370. rx_header:     ds.b  prhdr_sizeof
  5371. rxbuffer:      ds.b  PKTBUF_SIZE-prhdr_sizeof  ; received packet buffer
  5372.  
  5373.  CNOP 0,8
  5374. txbuffer:      ds.b  PKTBUF_SIZE               ; transmit packet buffer
  5375.  
  5376.  
  5377. ; Magically avoid PhxAss object generation bug
  5378. ; (don't ask me why this helps, but it does)
  5379.                dc.b  0
  5380.  
  5381.  CNOP 0,2
  5382. Endcode:
  5383.